0ac4beaaa8
- Add requireAuth() to admin-permissions.ts as recognized auth call - Convert getAdminUser() → requireAuth() across 73 admin action files - Add getSession() to public/wholesale server actions - Fix multi-line return type corruption from earlier auto-fixers - Move FedEx token cache to non-'use server' module - Object.freeze module-level constants: PRICE_KEYS, EMPTY_MOBILE_DASHBOARD, EMPTY_PAY_PERIOD, LOCALE_CART_SUBJECT, WELCOME_EMAILS - Update Stripe API version 2026-05-27 → 2026-06-24 - Fix wholesale employee portal: getEmployeeSessionAction + EmployeePortalClient - Fix 51 TypeScript errors (return type corruption, missing imports)
6850 lines
253 KiB
Plaintext
6850 lines
253 KiB
Plaintext
React Doctor v0.5.8
|
||
|
||
|
||
✔ Scanned 678 files in 23.8s [~20 workers]
|
||
|
||
✖ Bugs: Unauthenticated server action can be called directly ×95
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/server-auth-actions
|
||
Anyone can call server action "logAdminAction" without
|
||
logging in, since it has no auth check.
|
||
→ Check auth before touching data because exported server
|
||
actions can be called directly by unauthenticated clients.
|
||
|
||
src/actions/admin/audit.ts:22
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 21 | │
|
||
│ > 22 | export async function logAdminAction(payload: AdminA[0m… │
|
||
│ | ^ │
|
||
│ 23 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/admin/audit.ts:39
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 38 | │
|
||
│ > 39 | export async function logUserActivity(payload: UserA[0m… │
|
||
│ | ^ │
|
||
│ 40 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/admin/users.ts:158
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 157 | │
|
||
│ > 158 | export async function getAdminUsers(brandId?: strin[0m… │
|
||
│ | ^ │
|
||
│ 159 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/admin/users.ts:510
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 509 | │
|
||
│ > 510 | export async function updateAdminUser(input: Update[0m… │
|
||
│ | ^ │
|
||
│ 511 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/admin/users.ts:546
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 545 | │
|
||
│ > 546 | export async function deleteAdminUser(id: string): [0m… │
|
||
│ | ^ │
|
||
│ 547 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/admin/users.ts:556
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 555 | │
|
||
│ > 556 | export async function setMustChangePassword(userId:[0m… │
|
||
│ | ^ │
|
||
│ 557 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/admin/users.ts:624
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 623 | │
|
||
│ > 624 | export async function getBrands(): Promise<{ brands[0m… │
|
||
│ | ^ │
|
||
│ 625 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/auth-actions.ts:10
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 9 | */ │
|
||
│ > 10 | export async function signOutAction(): Promise<void>[0m… │
|
||
│ | ^ │
|
||
│ 11 | console.log("[auth/sign-out] Signing out"); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/auth-actions.ts:27
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 26 | */ │
|
||
│ > 27 | export async function signInWithGoogleAction(input: { │
|
||
│ | ^ │
|
||
│ 28 | callbackURL?: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/billing/retail-checkout.ts:15
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 14 | │
|
||
│ > 15 | export async function createRetailStripeCheckoutSess[0m… │
|
||
│ | ^ │
|
||
│ 16 | items: LineItem[], │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/billing/retail-payment-intent.ts:35
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 34 | │
|
||
│ > 35 | export async function createRetailPaymentIntent( │
|
||
│ | ^ │
|
||
│ 36 | items: LineItem[], │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/billing/stripe-checkout.ts:82
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 81 | │
|
||
│ > 82 | export async function createPlanUpgradeCheckout( │
|
||
│ | ^ │
|
||
│ 83 | brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/billing/stripe-checkout.ts:100
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 99 | │
|
||
│ > 100 | export async function createAddonCheckoutSession( │
|
||
│ | ^ │
|
||
│ 101 | brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/billing/stripe-portal.ts:100
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 99 | │
|
||
│ > 100 | export async function getBrandPlanInfo(brandId: str[0m… │
|
||
│ | ^ │
|
||
│ 101 | // Replicate get_brand_plan_info via a JOIN on te[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/billing/stripe-portal.ts:134
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 133 | │
|
||
│ > 134 | export async function getEnabledAddons(brandId: str[0m… │
|
||
│ | ^ │
|
||
│ 135 | // get_brand_features returns JSONB — a single ob[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/billing/stripe-portal.ts:149
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 148 | │
|
||
│ > 149 | export async function getRecentWholesaleOrders(bran[0m… │
|
||
│ | ^ │
|
||
│ 150 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/brand-settings.ts:234
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 233 | │
|
||
│ > 234 | export async function getBrandSettings(brandId: str[0m… │
|
||
│ | ^ │
|
||
│ 235 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/brand-settings.ts:255
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 254 | // has the same shape and never fails because of a [0m… │
|
||
│ > 255 | export async function getBrandSettingsPublic(brandS[0m… │
|
||
│ | ^ │
|
||
│ 256 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/checkout.ts:57
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 56 | │
|
||
│ > 57 | export async function createOrder( │
|
||
│ | ^ │
|
||
│ 58 | idempotencyKey: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/checkout.ts:164
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 163 | │
|
||
│ > 164 | export async function getServerCart(userId: string)[0m… │
|
||
│ | ^ │
|
||
│ 165 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/checkout.ts:177
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 176 | │
|
||
│ > 177 | export async function mergeLocalCart( │
|
||
│ | ^ │
|
||
│ 178 | localCart: CartItem[], │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/checkout.ts:235
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 234 | │
|
||
│ > 235 | export async function clearServerCart(userId: strin[0m… │
|
||
│ | ^ │
|
||
│ 236 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/checkout.ts:258
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 257 | │
|
||
│ > 258 | export async function getPublicStopsForBrand(brandI[0m… │
|
||
│ | ^ │
|
||
│ 259 | const { rows } = await pool.query<PublicStop>( │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/checkout.ts:274
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 273 | │
|
||
│ > 274 | export async function checkStopProductAvailability( │
|
||
│ | ^ │
|
||
│ 275 | stopId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/communications/contacts.ts:551
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 550 | │
|
||
│ > 551 | export async function previewContactImport( │
|
||
│ | ^ │
|
||
│ 552 | csvText: string │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/communications/settings.ts:48
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 47 | │
|
||
│ > 48 | export async function getCommunicationSettings(brand[0m… │
|
||
│ | ^ │
|
||
│ 49 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/email-automation/abandoned-cart.ts:180
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 179 | │
|
||
│ > 180 | export async function sendAbandonedCartEmail( │
|
||
│ | ^ │
|
||
│ 181 | cart: AbandonedCart, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/email-automation/abandoned-cart.ts:246
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 245 | │
|
||
│ > 246 | export async function markCartRecovered(cartId: str[0m… │
|
||
│ | ^ │
|
||
│ 247 | void cartId; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/email-automation/welcome-sequence.ts:181
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 180 | │
|
||
│ > 181 | export async function sendWelcomeEmail( │
|
||
│ | ^ │
|
||
│ 182 | entry: WelcomeSequenceEntry, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/integrations/ai-providers.ts:35
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 34 | │
|
||
│ > 35 | export async function getAIProviderSettings(brandId:[0m… │
|
||
│ | ^ │
|
||
│ 36 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/integrations/ai-providers.ts:98
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 97 | │
|
||
│ > 98 | export async function getAIClient(brandId: string): [0m… │
|
||
│ | ^ │
|
||
│ 99 | provider: AIProvider; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/integrations/ai-providers.ts:195
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 194 | │
|
||
│ > 195 | export async function getCustomIntegrations(brandId[0m… │
|
||
│ | ^ │
|
||
│ 196 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/integrations/credentials.ts:26
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 25 | │
|
||
│ > 26 | export async function getResendCredentials(brandId: [0m… │
|
||
│ | ^ │
|
||
│ 27 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/integrations/credentials.ts:87
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 86 | │
|
||
│ > 87 | export async function getTwilioCredentials(brandId: [0m… │
|
||
│ | ^ │
|
||
│ 88 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/integrations/credentials.ts:148
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 147 | │
|
||
│ > 148 | export async function testResendConnection(apiKey: [0m… │
|
||
│ | ^ │
|
||
│ 149 | ok: boolean; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/integrations/credentials.ts:176
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 175 | │
|
||
│ > 176 | export async function testTwilioConnection( │
|
||
│ | ^ │
|
||
│ 177 | accountSid: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/locations.ts:224
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 223 | │
|
||
│ > 224 | export async function getPublicLocationsForBrand( │
|
||
│ | ^ │
|
||
│ 225 | brandSlug: string │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/offline-dispatcher.ts:48
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 47 | │
|
||
│ > 48 | export async function listClientActions(): Promise<C[0m… │
|
||
│ | ^ │
|
||
│ 49 | // Wire real server actions here as they land: │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/offline-dispatcher.ts:57
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 56 | │
|
||
│ > 57 | export async function dispatchClientAction( │
|
||
│ | ^ │
|
||
│ 58 | actionName: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/payments.ts:28
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 27 | │
|
||
│ > 28 | export async function getPaymentSettings(brandId: st[0m… │
|
||
│ | ^ │
|
||
│ 29 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/route-trace/lots.ts:345
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 344 | */ │
|
||
│ > 345 | export async function getLotIdByNumber(_lotNumber: [0m… │
|
||
│ | ^ │
|
||
│ 346 | return null; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/stops.ts:153
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 152 | │
|
||
│ > 153 | export async function getActiveStopsForSitemap(): P[0m… │
|
||
│ | ^ │
|
||
│ 154 | // Wrapped in try/catch so a build-time outage (E[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/stops.ts:186
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 185 | │
|
||
│ > 186 | export async function getPublicStopsForBrand( │
|
||
│ | ^ │
|
||
│ 187 | brandSlug: string │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/storefront.ts:60
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 59 | */ │
|
||
│ > 60 | export async function getStorefrontBrandBySlug( │
|
||
│ | ^ │
|
||
│ 61 | slug: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/storefront.ts:77
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 76 | */ │
|
||
│ > 77 | export async function getStorefrontStops(brandId: st[0m… │
|
||
│ | ^ │
|
||
│ 78 | const { rows } = await pool.query<StorefrontStop>( │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/storefront.ts:101
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 100 | */ │
|
||
│ > 101 | export async function getStorefrontProducts( │
|
||
│ | ^ │
|
||
│ 102 | brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/storefront.ts:126
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 125 | */ │
|
||
│ > 126 | export async function getStorefrontData(slug: strin[0m… │
|
||
│ | ^ │
|
||
│ 127 | const brand = await getStorefrontBrandBySlug(slug[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/storefront.ts:149
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 148 | */ │
|
||
│ > 149 | export async function getStorefrontWholesaleSetting[0m… │
|
||
│ | ^ │
|
||
│ 150 | slug: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/storefront.ts:175
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 174 | */ │
|
||
│ > 175 | export async function getWholesalePortalConfig( │
|
||
│ | ^ │
|
||
│ 176 | brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/storefront.ts:195
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 194 | */ │
|
||
│ > 195 | export async function getStorefrontBrandName( │
|
||
│ | ^ │
|
||
│ 196 | brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/storefront.ts:216
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 215 | */ │
|
||
│ > 216 | export async function getStorefrontStopById(id: str[0m… │
|
||
│ | ^ │
|
||
│ 217 | stop: StorefrontStop; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/stripe-connect.ts:173
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 172 | */ │
|
||
│ > 173 | export async function saveStripeConnectAccount(bran[0m… │
|
||
│ | ^ │
|
||
│ 174 | success: boolean; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/tax.ts:27
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 26 | │
|
||
│ > 27 | export async function calculateOrderTax(params: { │
|
||
│ | ^ │
|
||
│ 28 | brandId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/tax.ts:196
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 195 | │
|
||
│ > 196 | export async function getTaxSummaryAction(params: { │
|
||
│ | ^ │
|
||
│ 197 | brandId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/tax.ts:231
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 230 | │
|
||
│ > 231 | export async function getTaxableOrdersAction(params[0m… │
|
||
│ | ^ │
|
||
│ 232 | brandId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/field.ts:55
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 54 | │
|
||
│ > 55 | export async function verifyTimeTrackingPin( │
|
||
│ | ^ │
|
||
│ 56 | _brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/field.ts:107
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 106 | │
|
||
│ > 107 | export async function logoutTimeTracking(): Promise[0m… │
|
||
│ | ^ │
|
||
│ 108 | const cookieStore = await cookies(); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/field.ts:114
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 113 | │
|
||
│ > 114 | export async function getTimeTrackingSession(): Pro[0m… │
|
||
│ | ^ │
|
||
│ 115 | const cookieStore = await cookies(); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/field.ts:132
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 131 | │
|
||
│ > 132 | export async function getTimeTrackingTasksField( │
|
||
│ | ^ │
|
||
│ 133 | _brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/index.ts:66
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 65 | │
|
||
│ > 66 | export async function getTimeTrackingWorkers(_brandI[0m… │
|
||
│ | ^ │
|
||
│ 67 | // Time tracking tables not in SaaS rebuild — retu[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/index.ts:108
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 107 | │
|
||
│ > 108 | export async function getTimeTrackingTasks(_brandId[0m… │
|
||
│ | ^ │
|
||
│ 109 | return []; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/index.ts:145
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 144 | │
|
||
│ > 145 | export async function getWorkerTimeLogs( │
|
||
│ | ^ │
|
||
│ 146 | _brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/index.ts:178
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 177 | │
|
||
│ > 178 | export async function getTimeTrackingSummary( │
|
||
│ | ^ │
|
||
│ 179 | _brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/index.ts:207
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 206 | │
|
||
│ > 207 | export async function getTimeTrackingSettings(_bran[0m… │
|
||
│ | ^ │
|
||
│ 208 | // Real RPC not in SaaS rebuild. │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/index.ts:253
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 252 | │
|
||
│ > 253 | export async function getTimeTrackingNotificationLo[0m… │
|
||
│ | ^ │
|
||
│ 254 | _brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/admin.ts:127
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 126 | */ │
|
||
│ > 127 | export async function requireWaterAdminSession(): P[0m… │
|
||
│ | ^ │
|
||
│ 128 | | { ok: true; adminUserId: string; brandId: strin[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/admin.ts:482
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 481 | │
|
||
│ > 482 | export async function createWaterIrrigator( │
|
||
│ | ^ │
|
||
│ 483 | brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/field.ts:68
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 67 | │
|
||
│ > 68 | export async function getWaterHeadgates( │
|
||
│ | ^ │
|
||
│ 69 | _brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/field.ts:98
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 97 | │
|
||
│ > 98 | export async function verifyWaterPin( │
|
||
│ | ^ │
|
||
│ 99 | _brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/field.ts:281
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 280 | │
|
||
│ > 281 | export async function requireFieldSession(): Promis[0m… │
|
||
│ | ^ │
|
||
│ 282 | const cookieStore = await cookies(); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/field.ts:342
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 341 | │
|
||
│ > 342 | export async function logoutWater(): Promise<void> { │
|
||
│ | ^ │
|
||
│ 343 | const cookieStore = await cookies(); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/field.ts:358
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 357 | │
|
||
│ > 358 | export async function logoutWaterAdmin(): Promise<v[0m… │
|
||
│ | ^ │
|
||
│ 359 | const cookieStore = await cookies(); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/field.ts:375
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 374 | │
|
||
│ > 375 | export async function getWaterSession(): Promise<st[0m… │
|
||
│ | ^ │
|
||
│ 376 | const cookieStore = await cookies(); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/field.ts:389
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 388 | */ │
|
||
│ > 389 | export async function getWaterAdminSession(): Promi[0m… │
|
||
│ | ^ │
|
||
│ 390 | sessionId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/field.ts:421
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 420 | │
|
||
│ > 421 | export async function setWaterLang(lang: string): P[0m… │
|
||
│ | ^ │
|
||
│ 422 | if (!["en", "es"].includes(lang)) return; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/water-log/settings.ts:188
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 187 | */ │
|
||
│ > 188 | export async function verifyWaterAdminPin( │
|
||
│ | ^ │
|
||
│ 189 | brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-auth.ts:33
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 32 | │
|
||
│ > 33 | export async function wholesaleLoginAction(_formData[0m… │
|
||
│ | ^ │
|
||
│ 34 | return { success: false, error: NOT_AVAILABLE_ERRO[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-auth.ts:37
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 36 | │
|
||
│ > 37 | export async function wholesaleLogoutAction(): Promi[0m… │
|
||
│ | ^ │
|
||
│ 38 | const cookieStore = await cookies(); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:7
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 6 | │
|
||
│ > 7 | export async function registerWholesaleCustomer(param[0m… │
|
||
│ | ^ │
|
||
│ 8 | brandId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:88
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 87 | │
|
||
│ > 88 | export async function getWholesaleCustomerByUser( │
|
||
│ | ^ │
|
||
│ 89 | brandId: string, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:124
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 123 | // Fetch a wholesale customer directly by their cus[0m… │
|
||
│ > 124 | export async function getWholesaleCustomer( │
|
||
│ | ^ │
|
||
│ 125 | customerId: string │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:161
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 160 | │
|
||
│ > 161 | export async function getWholesaleProducts(brandId:[0m… │
|
||
│ | ^ │
|
||
│ 162 | // Uses SECURITY DEFINER RPC — no auth required f[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:174
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 173 | │
|
||
│ > 174 | export async function submitWholesaleOrder(params: { │
|
||
│ | ^ │
|
||
│ 175 | brandId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:261
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 260 | │
|
||
│ > 261 | export async function enqueueWholesaleWebhookForOrd[0m… │
|
||
│ | ^ │
|
||
│ 262 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:316
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 315 | │
|
||
│ > 316 | export async function getWholesaleCustomerPricing(c[0m… │
|
||
│ | ^ │
|
||
│ 317 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:328
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 327 | │
|
||
│ > 328 | export async function upsertWholesaleCustomerPricin[0m… │
|
||
│ | ^ │
|
||
│ 329 | customerId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:344
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 343 | │
|
||
│ > 344 | export async function deleteWholesaleCustomerPricin[0m… │
|
||
│ | ^ │
|
||
│ 345 | customerId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale-register.ts:359
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 358 | │
|
||
│ > 359 | export async function getWholesaleCustomerOrders(cu[0m… │
|
||
│ | ^ │
|
||
│ 360 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale/notifications.ts:7
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 6 | │
|
||
│ > 7 | export async function getWholesaleNotificationStats( │
|
||
│ | ^ │
|
||
│ 8 | brandId: string │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale/notifications.ts:59
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 58 | │
|
||
│ > 59 | export async function enqueueWholesaleNotification(p[0m… │
|
||
│ | ^ │
|
||
│ 60 | brandId: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale/orders.ts:42
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 41 | │
|
||
│ > 42 | export async function getWholesaleDashboardStats(bra[0m… │
|
||
│ | ^ │
|
||
│ 43 | const orders = await getWholesaleOrders(brandId); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale/settings.ts:27
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 26 | │
|
||
│ > 27 | export async function getWholesaleSettingsPublic(bra[0m… │
|
||
│ | ^ │
|
||
│ 28 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale/webhooks.ts:7
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 6 | │
|
||
│ > 7 | export async function getWebhookSettings(brandId: str[0m… │
|
||
│ | ^ │
|
||
│ 8 | try { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale/webhooks.ts:47
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 46 | │
|
||
│ > 47 | export async function enqueueWholesaleWebhook( │
|
||
│ | ^ │
|
||
│ 48 | eventType: "order_created" | "order_fulfilled" | "[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/wholesale/webhooks.ts:65
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 64 | │
|
||
│ > 65 | export async function getRecentWebhookActivity(brand[0m… │
|
||
│ | ^ │
|
||
│ 66 | id: string; │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
✖ Security: socket/low-supply-chain-score
|
||
`vitest@2.1.9 (lowest version "^2.1.9" allows)` scored
|
||
25/100 on Socket's vulnerability axis (minimum 50). This
|
||
points to known security vulnerabilities (CVEs) affecting
|
||
this version. Other axes — supply chain 97, maintenance 98,
|
||
quality 78, license 100.
|
||
→ Upgrade to a version with no known advisories (run `npm
|
||
audit` to find one), or replace it; update `"vitest":
|
||
"^2.1.9"` in package.json. Full report:
|
||
https://socket.dev/npm/package/vitest/overview/2.1.9. If
|
||
you've reviewed and accepted this package, raise
|
||
`supplyChain.minScore` (currently 50) or set
|
||
`supplyChain.severity: "warning"`.
|
||
|
||
package.json:86
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 85 | "vite-tsconfig-paths": "^5.1.4", │
|
||
│ > 86 | "vitest": "^2.1.9" │
|
||
│ | ^ │
|
||
│ 87 | }, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
✖ Security: Side effect in GET handler ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/nextjs-no-side-effect-in-get-handler
|
||
This GET handler's side effect (fetch() with method POST)
|
||
is prone to CSRF vulnerabilities, since prefetching or a
|
||
forged request can trigger it.
|
||
→ GET requests can be prefetched and are open to CSRF. Move
|
||
the side effect to a POST handler.
|
||
|
||
src/app/api/square/oauth/callback/route.ts:5
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 4 | │
|
||
│ > 5 | export async function GET(request: Request) { │
|
||
│ | ^ │
|
||
│ 6 | const { searchParams } = new URL(request.url); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/app/api/stripe/oauth/callback/route.ts:5
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 4 | │
|
||
│ > 5 | export async function GET(req: Request) { │
|
||
│ | ^ │
|
||
│ 6 | const adminUser = await getAdminUser(); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
⚠ Security: HTML injection sink with dynamic content ×6
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/dangerous-html-sink
|
||
HTML is injected from a dynamic-looking source, which can
|
||
become XSS if the value is user-controlled or unsanitized.
|
||
→ Prefer rendering structured React nodes. If HTML is
|
||
required, sanitize with a well-reviewed sanitizer and keep
|
||
the trust boundary close to the sink.
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:176
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:475
|
||
|
||
src/app/wholesale/employee/page.tsx:244
|
||
|
||
src/components/admin/TemplateEditForm.tsx:652
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:281
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:404
|
||
|
||
✖ Bugs: Mutable module state on the server ×8
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/server-no-mutable-module-state
|
||
Module-scoped const "PRICE_KEYS = {}" leaks state between
|
||
your users, since every request shares it.
|
||
→ Keep per-request data inside the action, or in headers,
|
||
cookies, or `React.cache`. Module-scope `let`/`var` is
|
||
shared by every request.
|
||
|
||
src/actions/billing/stripe-checkout.ts:12
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 11 | │
|
||
│ > 12 | const PRICE_KEYS: Record<string, string | undefined>[0m… │
|
||
│ | ^ │
|
||
│ 13 | starter: process.env.STRIPE_PRICE_STARTER, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/dashboard.ts:47
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 46 | │
|
||
│ > 47 | const EMPTY_MOBILE_DASHBOARD: MobileDashboardSummary[0m… │
|
||
│ | ^ │
|
||
│ 48 | orders_today: 0, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/email-automation/abandoned-cart.ts:43
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 42 | │
|
||
│ > 43 | const LOCALE_CART_SUBJECT: Record<string, Record<num[0m… │
|
||
│ | ^ │
|
||
│ 44 | en: { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/email-automation/welcome-sequence.ts:44
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 43 | │
|
||
│ > 44 | const WELCOME_EMAILS: Record<string, Record<number, [0m… │
|
||
│ | ^ │
|
||
│ 45 | en: { │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/shipping/fedex-labels.ts:32
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 31 | │
|
||
│ > 32 | let cachedToken: FedExAuthToken | null = null; │
|
||
│ | ^ │
|
||
│ 33 | │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/shipping/fedex-rates.ts:63
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 62 | │
|
||
│ > 63 | let cachedToken: FedExAuthToken | null = null; │
|
||
│ | ^ │
|
||
│ 64 | │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/shipping/settings.ts:57
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 56 | │
|
||
│ > 57 | let cachedToken: FedExAuthToken | null = null; │
|
||
│ | ^ │
|
||
│ 58 | │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/actions/time-tracking/field.ts:157
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 156 | │
|
||
│ > 157 | const EMPTY_PAY_PERIOD: PayPeriodHours = { │
|
||
│ | ^ │
|
||
│ 158 | success: false, │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
⚠ Security: Raw SQL built outside parameter binding ×4
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/raw-sql-injection-risk
|
||
Code uses a raw SQL escape hatch or string-built query
|
||
shape that can bypass parameter binding.
|
||
→ Keep user input in driver parameters or ORM bind
|
||
variables. Avoid unsafe/raw SQL helpers and string
|
||
interpolation for queries.
|
||
|
||
src/actions/brand-settings.ts:175
|
||
|
||
src/actions/orders/update-order.ts:75
|
||
|
||
src/app/admin/stops/page.tsx:57
|
||
|
||
src/app/api/ai/customer-insights/route.ts:105
|
||
|
||
✖ Bugs: Effect subscription or timer never cleaned up
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/effect-needs-cleanup
|
||
`setTimeout` creates a timer in useEffect without returning
|
||
cleanup. Return a cleanup function so it does not leak
|
||
after unmount.
|
||
→ Return a cleanup function that stops the subscription or
|
||
timer: `return () => target.removeEventListener(name,
|
||
handler)` for listeners, `return () => clearInterval(id)`
|
||
or `clearTimeout(id)` for timers, or `return unsubscribe`
|
||
if the subscribe call already gave you one.
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:23
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 22 | │
|
||
│ > 23 | useEffect(() => { │
|
||
│ | ^ │
|
||
│ 24 | // Check if consent was already given │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
✖ Security: Permissive Supabase RLS policy
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/supabase-rls-policy-risk
|
||
Supabase policy SQL disables RLS, permits writes broadly,
|
||
or references a service-role bypass.
|
||
→ Keep public-read policies explicit, but gate inserts,
|
||
updates, deletes, and service-role bypasses behind
|
||
`auth.uid()` plus trusted tenant membership.
|
||
|
||
db/migrations/0001_init.sql:1758
|
||
|
||
⚠ Performance: Component defined inside a component
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-unstable-nested-components
|
||
Your users lose this component's state on every render
|
||
because it's defined inside another component
|
||
(`StopTableClient`).
|
||
→ Move nested components to module scope so React does not
|
||
remount them and lose state on every render.
|
||
|
||
src/components/admin/StopTableClient.tsx:259
|
||
|
||
⚠ Bugs: Array index used as a key ×82
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-array-index-as-key
|
||
Your users can see & submit the wrong data when this list
|
||
reorders or filters, so use a stable id like
|
||
`key={item.id}`, not the array index "i".
|
||
→ Use a stable id from the item, like `key={item.id}` or
|
||
`key={item.slug}`. Index keys break when the list reorders
|
||
or filters.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:283
|
||
|
||
src/app/admin/products/import/page.tsx:230
|
||
|
||
src/app/admin/sales/import/page.tsx:184
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:544
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:748
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:759
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:887
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:928
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:986
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1015
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1025
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1162
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1171
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1304
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1413
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1513
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1531
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1537
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1648
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1733
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1739
|
||
|
||
src/app/admin/settings/billing/BillingClientPage.tsx:215
|
||
|
||
src/app/blog/page.tsx:216
|
||
|
||
src/app/changelog/page.tsx:154
|
||
|
||
src/app/checkout/success/page.tsx:244
|
||
|
||
src/app/checkout/success/page.tsx:265
|
||
|
||
src/app/checkout/success/page.tsx:284
|
||
|
||
src/app/indian-river-direct/page.tsx:425
|
||
|
||
src/app/pricing/PricingClientPage.tsx:150
|
||
|
||
src/app/pricing/PricingClientPage.tsx:294
|
||
|
||
src/app/pricing/PricingClientPage.tsx:317
|
||
|
||
src/app/security/page.tsx:101
|
||
|
||
src/app/security/page.tsx:130
|
||
|
||
src/app/tuxedo/page.tsx:878
|
||
|
||
src/app/waitlist/page.tsx:102
|
||
|
||
src/app/wholesale/employee/page.tsx:490
|
||
|
||
src/app/wholesale/portal/page.tsx:671
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:229
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:997
|
||
|
||
src/components/admin/AdvancedSettingsClient.tsx:175
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:105
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:171
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:226
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:316
|
||
|
||
src/components/admin/ContactImportForm.tsx:597
|
||
|
||
src/components/admin/ContactImportForm.tsx:703
|
||
|
||
src/components/admin/ContactImportForm.tsx:733
|
||
|
||
src/components/admin/ProductSyncBanner.tsx:89
|
||
|
||
src/components/admin/ReportsDashboard.tsx:687
|
||
|
||
src/components/admin/ReportsDashboard.tsx:698
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:225
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:254
|
||
|
||
src/components/admin/SettingsSections.tsx:319
|
||
|
||
src/components/admin/StatsStrip.tsx:18
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:528
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:257
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:55
|
||
|
||
src/components/admin/design-system/AdminStatsBar.tsx:24
|
||
|
||
src/components/admin/design-system/PageHeader.tsx:35
|
||
|
||
src/components/admin/shared/FilterBar.tsx:57
|
||
|
||
src/components/admin/shared/PageHeader.tsx:18
|
||
|
||
src/components/admin/stops/StopsCalendar.tsx:252
|
||
|
||
src/components/landing/FeaturesAndStats.tsx:489
|
||
|
||
src/components/landing/FeaturesAndStats.tsx:616
|
||
|
||
src/components/landing/HeroSection.tsx:392
|
||
|
||
src/components/landing/HeroSection.tsx:761
|
||
|
||
src/components/landing/HeroSection.tsx:862
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:175
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:295
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:289
|
||
|
||
src/components/referral/ReferralSystem.tsx:126
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:526
|
||
|
||
src/components/route-trace/RouteTraceDashboard.tsx:467
|
||
|
||
src/components/shared/LoadingSkeleton.tsx:83
|
||
|
||
src/components/shared/LoadingSkeleton.tsx:95
|
||
|
||
src/components/shared/LoadingSkeleton.tsx:104
|
||
|
||
src/components/shared/LoadingSkeleton.tsx:113
|
||
|
||
src/components/storefront/BreadcrumbNav.tsx:49
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:282
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:367
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:90
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:238
|
||
|
||
⚠ Bugs: Missing effect dependencies ×12
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/exhaustive-deps
|
||
`useCallback` can run with a stale `setSelectedStop` & show
|
||
your users old data.
|
||
→ Don't blindly add missing dependencies. Read the hook
|
||
callback first.
|
||
|
||
Bad:
|
||
useEffect(() => {
|
||
setCount(count + 1);
|
||
}, [count]);
|
||
|
||
Better:
|
||
useEffect(() => {
|
||
setCount((currentCount) => currentCount + 1);
|
||
}, []);
|
||
|
||
If the missing value is recreated every render, move it
|
||
inside the hook or stabilize it before adding it to deps.
|
||
|
||
src/app/cart/CartClient.tsx:86
|
||
|
||
src/app/checkout/CheckoutClient.tsx:141
|
||
|
||
src/components/admin/CartHydration.tsx:15
|
||
↳ oxlint matches plugin rules only by their full name, so `react-hooks/exhaustive-deps` in your eslint-disable comment does not silence `react-doctor/exhaustive-deps` — change it to `react-doctor/exhaustive-deps`.
|
||
|
||
src/components/admin/MessageLogPanel.tsx:242
|
||
|
||
src/components/admin/ReportsDashboard.tsx:315
|
||
↳ oxlint matches plugin rules only by their full name, so `react-hooks/exhaustive-deps` in your eslint-disable comment does not silence `react-doctor/exhaustive-deps` — change it to `react-doctor/exhaustive-deps`.
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:184
|
||
|
||
src/components/route-trace/QRScanModal.tsx:179
|
||
|
||
src/components/storefront/StripeExpressCheckout.tsx:150
|
||
↳ oxlint matches plugin rules only by their full name, so `react-hooks/exhaustive-deps` in your eslint-disable comment does not silence `react-doctor/exhaustive-deps` — change it to `react-doctor/exhaustive-deps`.
|
||
|
||
src/components/storefront/StripeExpressCheckout.tsx:156
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:236
|
||
↳ oxlint matches plugin rules only by their full name, so `react-hooks/exhaustive-deps` in your eslint-disable comment does not silence `react-doctor/exhaustive-deps` — change it to `react-doctor/exhaustive-deps`.
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:256
|
||
|
||
src/components/water/WaterFieldClient.tsx:166
|
||
↳ oxlint matches plugin rules only by their full name, so `react-hooks/exhaustive-deps` in your eslint-disable comment does not silence `react-doctor/exhaustive-deps` — change it to `react-doctor/exhaustive-deps`.
|
||
|
||
⚠ Bugs: Time or random value in JSX ×23
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/rendering-hydration-mismatch-time
|
||
This can cause a hydration mismatch because new Date()
|
||
reached from JSX gives a different value on the server than
|
||
in the browser. Move it into useEffect+useState to run only
|
||
in the browser, or add suppressHydrationWarning to the
|
||
parent if it's on purpose.
|
||
→ Move time or random values into useEffect+useState so
|
||
they only run in the browser, or add
|
||
suppressHydrationWarning to the parent if it's intentional
|
||
|
||
src/app/admin/v2/page.tsx:88
|
||
|
||
src/app/admin/v2/page.tsx:133
|
||
|
||
src/app/blog/page.tsx:263
|
||
|
||
src/app/brands/page.tsx:215
|
||
|
||
src/app/changelog/page.tsx:211
|
||
|
||
src/app/contact/ContactClientPage.tsx:285
|
||
|
||
src/app/privacy-policy/page.tsx:67
|
||
|
||
src/app/privacy-policy/page.tsx:129
|
||
|
||
src/app/roadmap/page.tsx:249
|
||
|
||
src/app/security/page.tsx:260
|
||
|
||
src/app/terms-and-conditions/page.tsx:67
|
||
|
||
src/app/terms-and-conditions/page.tsx:131
|
||
|
||
src/app/waitlist/page.tsx:121
|
||
|
||
src/app/wholesale/portal/page.tsx:822
|
||
|
||
src/components/admin/CampaignListPanel.tsx:668
|
||
|
||
src/components/admin/HarvestReach/AnalyticsDashboard.tsx:432
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:781
|
||
|
||
src/components/admin/ReportsDashboard.tsx:387
|
||
|
||
src/components/admin/TaxDashboard.tsx:312
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:381
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:299
|
||
|
||
src/components/layout/SiteFooter.tsx:37
|
||
|
||
src/components/storefront/StorefrontFooter.tsx:201
|
||
|
||
⚠ Bugs: Sequential independent awaits ×29
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/server-sequential-independent-await
|
||
This await doesn't use the previous result, so your users
|
||
wait twice as long for nothing.
|
||
→ These two awaits don't depend on each other. Wrap them in
|
||
`Promise.all([...])` so they run at the same time.
|
||
|
||
src/actions/communications/stop-blast.ts:59
|
||
|
||
src/actions/communications/stop-messaging.ts:81
|
||
|
||
src/actions/harvest-reach/segments.ts:238
|
||
|
||
src/actions/shipping/fedex-rates.ts:196
|
||
|
||
src/actions/stops/get-stop-details.ts:88
|
||
|
||
src/actions/water-log/field.ts:149
|
||
|
||
src/app/admin/pickup/page.tsx:13
|
||
|
||
src/app/admin/route-trace/lots/[id]/page.tsx:25
|
||
|
||
src/app/admin/settings/page.tsx:37
|
||
|
||
src/app/admin/stops/[id]/page.tsx:58
|
||
|
||
src/app/admin/stops/[id]/page.tsx:139
|
||
|
||
src/app/admin/stops/new/page.tsx:36
|
||
|
||
src/app/admin/stops/page.tsx:22
|
||
|
||
src/app/admin/v2/orders/[id]/page.tsx:35
|
||
|
||
src/app/admin/v2/products/page.tsx:81
|
||
|
||
src/app/admin/v2/stops/page.tsx:133
|
||
|
||
src/app/admin/water-log/entries/[id]/page.tsx:18-21
|
||
|
||
src/app/admin/water-log/headgates/[id]/page.tsx:19-22
|
||
|
||
src/app/admin/water-log/users/[id]/page.tsx:19-22
|
||
|
||
src/app/api/indian-river-direct/schedule-pdf/route.ts:25
|
||
|
||
src/app/api/indian-river-direct/schedule-pdf/route.ts:77
|
||
|
||
src/app/api/tuxedo/schedule-pdf/route.ts:25
|
||
|
||
src/app/api/tuxedo/schedule-pdf/route.ts:77
|
||
|
||
src/app/api/wholesale/invoice/[orderId]/pdf/route.ts:122
|
||
|
||
src/app/api/wholesale/invoice/[orderId]/route.ts:115
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:388
|
||
|
||
⚠ Accessibility: Label missing associated control ×284
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/label-has-associated-control
|
||
Screen reader users can't tell which input this label names
|
||
because it's tied to none, so add `htmlFor` or wrap the
|
||
input inside it.
|
||
→ Tie every label to a control with `htmlFor`, or by
|
||
nesting the input.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:164
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:883
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:917
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1102
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1106
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1110
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1114
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1232
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1390
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1403
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1424
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1435
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1446
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1457
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1469
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1625
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1629
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1637
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:311
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:396
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:552
|
||
|
||
src/app/change-password/ChangePasswordForm.tsx:84
|
||
|
||
src/app/change-password/ChangePasswordForm.tsx:100
|
||
|
||
src/app/change-password/page.tsx:75
|
||
|
||
src/app/change-password/page.tsx:91
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:164
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:175
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:188
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:201
|
||
|
||
src/app/reset-password/page.tsx:99
|
||
|
||
src/app/reset-password/page.tsx:114
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:133
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:143
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:155
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:168
|
||
|
||
src/app/wholesale/portal/page.tsx:814
|
||
|
||
src/components/admin/AIProviderPanel.tsx:229
|
||
|
||
src/components/admin/AIProviderPanel.tsx:251
|
||
|
||
src/components/admin/AIProviderPanel.tsx:281
|
||
|
||
src/components/admin/AIProviderPanel.tsx:296
|
||
|
||
src/components/admin/AddLocationModal.tsx:121
|
||
|
||
src/components/admin/AddLocationModal.tsx:136
|
||
|
||
src/components/admin/AddLocationModal.tsx:151
|
||
|
||
src/components/admin/AddLocationModal.tsx:164
|
||
|
||
src/components/admin/AddLocationModal.tsx:178
|
||
|
||
src/components/admin/AddLocationModal.tsx:194
|
||
|
||
src/components/admin/AddLocationModal.tsx:207
|
||
|
||
src/components/admin/AddLocationModal.tsx:222
|
||
|
||
src/components/admin/AddLocationModal.tsx:236
|
||
|
||
src/components/admin/AddStopModal.tsx:309
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:941
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:390
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:418
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:446
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:463
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:198
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:221
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:235
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:293
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:307
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:330
|
||
|
||
src/components/admin/AdvancedShipping.tsx:108
|
||
|
||
src/components/admin/AdvancedShipping.tsx:123
|
||
|
||
src/components/admin/AdvancedShipping.tsx:135
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:99
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:109
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:119
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:491
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:510
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:529
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:548
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:614
|
||
|
||
src/components/admin/CampaignListPanel.tsx:149
|
||
|
||
src/components/admin/CampaignListPanel.tsx:163
|
||
|
||
src/components/admin/CampaignListPanel.tsx:482
|
||
|
||
src/components/admin/CampaignListPanel.tsx:493
|
||
|
||
src/components/admin/CampaignListPanel.tsx:505
|
||
|
||
src/components/admin/CampaignListPanel.tsx:545
|
||
|
||
src/components/admin/CampaignListPanel.tsx:563
|
||
|
||
src/components/admin/CampaignListPanel.tsx:573
|
||
|
||
src/components/admin/CampaignListPanel.tsx:582
|
||
|
||
src/components/admin/CampaignListPanel.tsx:616
|
||
|
||
src/components/admin/CampaignListPanel.tsx:626
|
||
|
||
src/components/admin/CampaignListPanel.tsx:662
|
||
|
||
src/components/admin/CreateUserModal.tsx:377
|
||
|
||
src/components/admin/CreateUserModal.tsx:420
|
||
|
||
src/components/admin/EditLocationModal.tsx:140
|
||
|
||
src/components/admin/EditLocationModal.tsx:154
|
||
|
||
src/components/admin/EditLocationModal.tsx:168
|
||
|
||
src/components/admin/EditLocationModal.tsx:180
|
||
|
||
src/components/admin/EditLocationModal.tsx:193
|
||
|
||
src/components/admin/EditLocationModal.tsx:208
|
||
|
||
src/components/admin/EditLocationModal.tsx:220
|
||
|
||
src/components/admin/EditLocationModal.tsx:234
|
||
|
||
src/components/admin/EditLocationModal.tsx:247
|
||
|
||
src/components/admin/EditStopModal.tsx:350
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:503
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:515
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:528
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:567
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:580
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:705
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:735
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:775
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:330
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:339
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:369
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:425
|
||
|
||
src/components/admin/HarvestReach/SegmentEditModal.tsx:77
|
||
|
||
src/components/admin/HarvestReach/SegmentEditModal.tsx:89
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:170
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:193
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:207
|
||
|
||
src/components/admin/NewProductForm.tsx:240
|
||
|
||
src/components/admin/NewStopForm.tsx:128
|
||
|
||
src/components/admin/NewStopForm.tsx:153
|
||
|
||
src/components/admin/NewStopForm.tsx:179
|
||
|
||
src/components/admin/NewStopForm.tsx:205
|
||
|
||
src/components/admin/NewStopForm.tsx:229
|
||
|
||
src/components/admin/NewStopForm.tsx:255
|
||
|
||
src/components/admin/NewStopForm.tsx:282
|
||
|
||
src/components/admin/NewStopForm.tsx:295
|
||
|
||
src/components/admin/NewStopForm.tsx:306
|
||
|
||
src/components/admin/NewStopForm.tsx:319
|
||
|
||
src/components/admin/OrderEditForm.tsx:267
|
||
|
||
src/components/admin/OrderEditForm.tsx:279
|
||
|
||
src/components/admin/OrderEditForm.tsx:328
|
||
|
||
src/components/admin/OrderEditForm.tsx:357
|
||
|
||
src/components/admin/OrderEditForm.tsx:395
|
||
|
||
src/components/admin/OrderEditForm.tsx:444
|
||
|
||
src/components/admin/OrderEditForm.tsx:462
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:173
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:189
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:205
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:277
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:303
|
||
|
||
src/components/admin/ProductEditForm.tsx:209
|
||
|
||
src/components/admin/ProductEditForm.tsx:223
|
||
|
||
src/components/admin/ProductEditForm.tsx:253
|
||
|
||
src/components/admin/SettingsSections.tsx:316
|
||
|
||
src/components/admin/SettingsSections.tsx:323
|
||
|
||
src/components/admin/SettingsSections.tsx:332
|
||
|
||
src/components/admin/SettingsSections.tsx:341
|
||
|
||
src/components/admin/SettingsSections.tsx:397
|
||
|
||
src/components/admin/SettingsSections.tsx:420
|
||
|
||
src/components/admin/SettingsSections.tsx:623
|
||
|
||
src/components/admin/SettingsSections.tsx:630
|
||
|
||
src/components/admin/SettingsSections.tsx:638
|
||
|
||
src/components/admin/SettingsSections.tsx:688
|
||
|
||
src/components/admin/SettingsSections.tsx:694
|
||
|
||
src/components/admin/SettingsSections.tsx:701
|
||
|
||
src/components/admin/SettingsSections.tsx:710
|
||
|
||
src/components/admin/StopEditForm.tsx:121
|
||
|
||
src/components/admin/StopEditForm.tsx:146
|
||
|
||
src/components/admin/StopEditForm.tsx:173
|
||
|
||
src/components/admin/StopEditForm.tsx:197
|
||
|
||
src/components/admin/StopEditForm.tsx:209
|
||
|
||
src/components/admin/StopEditForm.tsx:221
|
||
|
||
src/components/admin/StopEditForm.tsx:232
|
||
|
||
src/components/admin/StopEditForm.tsx:265
|
||
|
||
src/components/admin/StopMessagingForm.tsx:124
|
||
|
||
src/components/admin/StopMessagingForm.tsx:146
|
||
|
||
src/components/admin/StopMessagingForm.tsx:168
|
||
|
||
src/components/admin/TemplateEditForm.tsx:168
|
||
|
||
src/components/admin/TemplateEditForm.tsx:182
|
||
|
||
src/components/admin/TemplateEditForm.tsx:448
|
||
|
||
src/components/admin/TemplateEditForm.tsx:459
|
||
|
||
src/components/admin/TemplateEditForm.tsx:471
|
||
|
||
src/components/admin/TemplateEditForm.tsx:490
|
||
|
||
src/components/admin/TemplateEditForm.tsx:551
|
||
|
||
src/components/admin/TemplateEditForm.tsx:561
|
||
|
||
src/components/admin/TemplateEditForm.tsx:574
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:419
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:428
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:654
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:663
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:672
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:685
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:801
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:805
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:813
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:886
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:890
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:894
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:525
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:532
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:541
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:550
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:613
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:632
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:682
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:689
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:697
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:741
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:747
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:754
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:763
|
||
|
||
src/components/admin/UsersPage.tsx:542
|
||
|
||
src/components/admin/UsersPage.tsx:556
|
||
|
||
src/components/admin/UsersPage.tsx:571
|
||
|
||
src/components/admin/UsersPage.tsx:584
|
||
|
||
src/components/admin/UsersPage.tsx:597
|
||
|
||
src/components/admin/UsersPage.tsx:625
|
||
|
||
src/components/admin/UsersPage.tsx:657
|
||
|
||
src/components/admin/WaterLogEntryEditForm.tsx:74
|
||
|
||
src/components/admin/WaterLogEntryEditForm.tsx:78
|
||
|
||
src/components/admin/WaterLogEntryEditForm.tsx:100
|
||
|
||
src/components/admin/WaterLogEntryEditForm.tsx:104
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:90
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:100
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:116
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:130
|
||
|
||
src/components/admin/stops/StopsLocations.tsx:194
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:297
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:308
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:97
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:108
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:120
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:135
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:147
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:157
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:175
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:187
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:231
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:241
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:253
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:264
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:149
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:165
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:182
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:202
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:219
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:234
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:257
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:274
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:329
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:344
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:361
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:377
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:753
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:772
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:782
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:823
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:834
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:877
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:888
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:899
|
||
|
||
src/components/route-trace/QRScanModal.tsx:276
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:82
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:97
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:109
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:123
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:135
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:149
|
||
|
||
src/components/route-trace/RouteTraceSettings.tsx:68
|
||
|
||
src/components/route-trace/RouteTraceSettings.tsx:94
|
||
|
||
src/components/route-trace/RouteTraceSettings.tsx:120
|
||
|
||
src/components/water/WaterFieldClient.tsx:635
|
||
|
||
src/components/wholesale/DepositModal.tsx:58
|
||
|
||
src/components/wholesale/DepositModal.tsx:70
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:212
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:223
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:228
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:233
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:467
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:472
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:501
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:506
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:145
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:154
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:159
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:173
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:178
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:183
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:188
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:193
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:198
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:203
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:208
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:213
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:220
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:270
|
||
|
||
src/components/wholesale/admin/WebhookSettingsSection.tsx:117
|
||
|
||
src/components/wholesale/admin/WebhookSettingsSection.tsx:128
|
||
|
||
⚠ Performance: Independent awaits run sequentially ×5
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/async-parallel
|
||
These 3 sequential await statements run one after another
|
||
even though they look independent, so the page waits longer
|
||
than it needs to. Run them together with Promise.all()
|
||
instead
|
||
→ Use `const [a, b] = await Promise.all([fetchA(),
|
||
fetchB()])` so independent calls run at the same time
|
||
|
||
src/actions/water-log/settings.ts:162
|
||
|
||
src/app/admin/water-log/entries/[id]/page.tsx:17
|
||
|
||
src/app/admin/water-log/headgates/[id]/page.tsx:18
|
||
|
||
src/app/admin/water-log/users/[id]/page.tsx:18
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:387
|
||
|
||
⚠ Bugs: Derived state stored in an effect ×5
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-derived-state-effect
|
||
Your users briefly see stale state on every prop change.
|
||
→ Work out derived values while rendering: `const x =
|
||
fn(dep)`. To reset a component's state when a prop changes,
|
||
give it a key prop: `<Component key={prop} />`. See
|
||
https://react.dev/learn/you-might-not-need-an-effect
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:61
|
||
|
||
src/components/admin/AdminHeader.tsx:74
|
||
|
||
src/components/admin/CommandPalette.tsx:219
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:201
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:50
|
||
|
||
⚠ Performance: await inside a loop ×25
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/async-await-in-loop
|
||
This makes the for…of loop slow because each await runs one
|
||
after another, so collect the independent calls & run them
|
||
together with `await Promise.all(items.map(...))`
|
||
→ Collect the items, then use `await
|
||
Promise.all(items.map(...))` so independent work runs at
|
||
the same time
|
||
|
||
src/actions/communications/contacts.ts:347
|
||
|
||
src/actions/import-products.ts:48
|
||
|
||
src/actions/square-orders.ts:108
|
||
|
||
src/app/admin/page.tsx:74
|
||
|
||
src/app/api/cron/send-scheduled/route.ts:47
|
||
|
||
src/app/api/cron/send-scheduled/route.ts:71
|
||
|
||
src/app/api/email-automation/abandoned-cart/route.ts:30
|
||
|
||
src/app/api/email-automation/abandoned-cart/route.ts:56
|
||
|
||
src/app/api/email-automation/welcome-sequence/route.ts:27
|
||
|
||
src/app/api/email-automation/welcome-sequence/route.ts:53
|
||
|
||
src/app/api/time-tracking/export/route.ts:81
|
||
|
||
src/app/api/time-tracking/notify/route.ts:246
|
||
|
||
src/app/api/water-qr-sheet/route.ts:29
|
||
|
||
src/app/api/wholesale/notifications/send/route.ts:79
|
||
|
||
src/app/api/wholesale/notifications/send/route.ts:121
|
||
|
||
src/app/api/wholesale/webhooks/dispatch/route.ts:98
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:305
|
||
|
||
src/components/admin/OrderEditForm.tsx:142
|
||
|
||
src/components/admin/OrderEditForm.tsx:157
|
||
|
||
src/components/admin/StopProductAssignment.tsx:178
|
||
|
||
src/components/admin/StopTableClient.tsx:231
|
||
|
||
src/components/route-trace/LotListTable.tsx:165
|
||
|
||
src/lib/billing.ts:82
|
||
|
||
src/lib/billing.ts:210
|
||
|
||
src/lib/offline/sync.ts:47
|
||
|
||
⚠ Bugs: Prop derived into useState ×40
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-derived-useState
|
||
Your users see a stale value when prop "currentModel"
|
||
changes because useState copies it once.
|
||
→ Compute the value inline so prop changes do not leave
|
||
`useState` holding a stale copy.
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:332
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1806-1807
|
||
|
||
src/app/admin/settings/billing/BillingClient.tsx:19
|
||
|
||
src/app/admin/settings/billing/BillingClientPage.tsx:58
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:467
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:475
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClientPage.tsx:355
|
||
|
||
src/app/admin/settings/square-sync/SquareSyncSettingsClient.tsx:52
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:59
|
||
|
||
src/components/admin/CommunicationsLoading.tsx:247
|
||
|
||
src/components/admin/HeadgateEditForm.tsx:26-28
|
||
|
||
src/components/admin/IntegrationsInner.tsx:278
|
||
|
||
src/components/admin/OrderEditForm.tsx:64
|
||
|
||
src/components/admin/OrderEditForm.tsx:70-71
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:35
|
||
|
||
src/components/admin/ProductEditForm.tsx:39-44
|
||
|
||
src/components/admin/StopEditForm.tsx:41-47
|
||
|
||
src/components/admin/StopProductAssignment.tsx:49
|
||
|
||
src/components/admin/WaterLogEntryEditForm.tsx:32-33
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:25-28
|
||
|
||
src/components/admin/products/StockAdjustButton.tsx:33
|
||
|
||
⚠ Bugs: useSearchParams without Suspense ×5
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/nextjs-no-use-search-params-without-suspense
|
||
<OrdersFilterButton> uses useSearchParams() outside
|
||
<Suspense>, so this page falls back to client-side
|
||
rendering.
|
||
→ Wrap the component using `useSearchParams` in
|
||
`<Suspense>` so the rest of the page can stay statically
|
||
rendered.
|
||
|
||
src/app/admin/v2/orders/page.tsx:54
|
||
|
||
src/app/admin/v2/orders/page.tsx:69
|
||
|
||
src/app/admin/v2/products/page.tsx:140
|
||
|
||
src/app/admin/v2/products/page.tsx:156
|
||
|
||
src/app/admin/v2/products/page.tsx:174
|
||
|
||
⚠ Bugs: Unknown DOM property ×6
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-unknown-property
|
||
React ignores this prop because it doesn't recognize the
|
||
name.
|
||
→ Use the prop name React expects, like `className`,
|
||
`htmlFor`, or `tabIndex`, so the attribute is applied
|
||
correctly.
|
||
|
||
src/app/brands/page.tsx:225
|
||
|
||
src/components/landing/FeaturesAndStats.tsx:240
|
||
|
||
src/components/landing/HeroSection.tsx:988
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:628
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:66
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:441
|
||
|
||
⚠ Bugs: Client-side redirect for navigation ×9
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/nextjs-no-client-side-redirect
|
||
router.push() in useEffect flashes the wrong page before
|
||
redirecting.
|
||
→ Avoid redirects inside useEffect. Use an event handler,
|
||
middleware, or server-side redirect (App Router: redirect()
|
||
from next/navigation; Pages Router: getServerSideProps
|
||
redirect)
|
||
|
||
src/app/logout/page.tsx:14
|
||
|
||
src/app/logout/page.tsx:18
|
||
|
||
src/app/wholesale/employee/page.tsx:54
|
||
|
||
src/app/wholesale/employee/page.tsx:69
|
||
|
||
src/app/wholesale/portal/page.tsx:307
|
||
|
||
src/app/wholesale/portal/page.tsx:316
|
||
|
||
src/app/wholesale/portal/page.tsx:322
|
||
|
||
src/app/wholesale/portal/page.tsx:328
|
||
|
||
src/components/route-trace/QRScanModal.tsx:158
|
||
|
||
⚠ Bugs: Effects chained together ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-effect-chain
|
||
Your screen redraws several times from a single action
|
||
because one useEffect changes "selected", which sets off
|
||
this one.
|
||
→ Compute as much as possible during render (e.g. `const
|
||
isGameOver = round > 5`) and write all related state inside
|
||
the event handler that originally fires the chain. Each
|
||
effect link adds an extra render and makes the code rigid
|
||
as requirements evolve
|
||
|
||
src/components/admin/CommandPalette.tsx:224
|
||
|
||
src/context/CartContext.tsx:139
|
||
|
||
⚠ Maintainability: Component rendered by inline function call ×3
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-render-in-render
|
||
Your users lose state because "renderMappings()" builds UI
|
||
from an inline call that React remounts, so pull it into
|
||
its own component instead.
|
||
→ Make it a named component so React preserves its identity
|
||
and does not remount its state.
|
||
|
||
src/components/admin/ContactImportForm.tsx:613
|
||
|
||
src/components/admin/ContactImportForm.tsx:620
|
||
|
||
src/components/admin/ContactImportForm.tsx:627
|
||
|
||
⚠ Bugs: Hand-rolled external store subscription ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/prefer-use-sync-external-store
|
||
Your users can see stale or torn values because useState
|
||
"online" syncs an outside store through a useEffect.
|
||
→ Replace the `useState(getSnapshot())` + `useEffect(() =>
|
||
store.subscribe(() => setSnapshot(getSnapshot())))` pair
|
||
with `useSyncExternalStore(store.subscribe, getSnapshot)`.
|
||
The hook gets this right during concurrent rendering and on
|
||
the server; the hand-rolled version doesn't.
|
||
|
||
src/components/admin/OfflineBanner.tsx:7
|
||
|
||
src/components/admin/orders/OrdersFilterButton.tsx:20
|
||
|
||
⚠ Performance: Unstable context provider value ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/jsx-no-constructed-context-values
|
||
Every reader of this context redraws on each render because
|
||
you build its `value` inline.
|
||
→ Wrap the context value in `useMemo` or move it outside
|
||
the component so consumers do not redraw every render.
|
||
|
||
src/components/admin/Toast.tsx:61
|
||
|
||
src/context/CartContext.tsx:313
|
||
|
||
⚠ Performance: setState reads a stale value ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/rerender-functional-setstate
|
||
You can lose this update because setCurrentStep(currentStep
|
||
+ ...) reads a stale value.
|
||
→ Use the callback form: `setState(prev => prev + 1)` to
|
||
always read the latest value
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:104
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:110
|
||
|
||
⚠ Performance: array.find() inside a loop ×6
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/js-index-maps
|
||
This gets slow as your list grows because array.find() runs
|
||
inside a loop, so build a Map once before the loop for
|
||
instant lookups
|
||
→ Build a `Map` once before the loop instead of calling
|
||
`array.find(...)` inside it
|
||
|
||
src/app/api/time-tracking/export/route.ts:156
|
||
|
||
src/app/api/time-tracking/export/route.ts:196
|
||
|
||
src/app/api/time-tracking/export/route.ts:205
|
||
|
||
src/components/admin/OrderEditForm.tsx:151
|
||
|
||
src/components/admin/StopTableClient.tsx:229
|
||
|
||
src/lib/billing.ts:80
|
||
|
||
⚠ Accessibility: Control missing accessible label ×444
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/control-has-associated-label
|
||
Blind users can't tell what this control does because
|
||
screen readers find no label, so add visible text,
|
||
`aria-label`, or `aria-labelledby`.
|
||
→ Give every interactive control a label screen readers can
|
||
read.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:192
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:362
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:888
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:898
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:929
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:937
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:947
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1103
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1107
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1111
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1115
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1233
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1391
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1425
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1436
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1447
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1458
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1470
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1626
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1630
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1649
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1657
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1665
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1773
|
||
|
||
src/app/admin/settings/billing/BillingClientPage.tsx:407
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:312
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:567
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:616
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:622
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:271-272
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:285-286
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:369
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:507
|
||
|
||
src/app/blog/page.tsx:244
|
||
|
||
src/app/change-password/ChangePasswordForm.tsx:87
|
||
|
||
src/app/change-password/ChangePasswordForm.tsx:103
|
||
|
||
src/app/change-password/page.tsx:78
|
||
|
||
src/app/change-password/page.tsx:94
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:165
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:176
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:202
|
||
|
||
src/app/indian-river-direct/faq/FAQClientPage.tsx:171
|
||
|
||
src/app/indian-river-direct/faq/FAQClientPage.tsx:179
|
||
|
||
src/app/indian-river-direct/page.tsx:457
|
||
|
||
src/app/maintenance/page.tsx:62
|
||
|
||
src/app/maintenance/page.tsx:67
|
||
|
||
src/app/reset-password/page.tsx:102
|
||
|
||
src/app/reset-password/page.tsx:117
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:134
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:144
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:169
|
||
|
||
src/app/tuxedo/faq/FAQClientPage.tsx:160
|
||
|
||
src/app/tuxedo/faq/FAQClientPage.tsx:168
|
||
|
||
src/app/water/admin/login/WaterAdminPinClient.tsx:41
|
||
|
||
src/app/wholesale/employee/page.tsx:432
|
||
|
||
src/app/wholesale/employee/page.tsx:442
|
||
|
||
src/app/wholesale/login/page.tsx:256
|
||
|
||
src/app/wholesale/login/page.tsx:269
|
||
|
||
src/app/wholesale/portal/page.tsx:117
|
||
|
||
src/app/wholesale/portal/page.tsx:184
|
||
|
||
src/app/wholesale/portal/page.tsx:192
|
||
|
||
src/app/wholesale/portal/page.tsx:749
|
||
|
||
src/app/wholesale/portal/page.tsx:818
|
||
|
||
src/app/wholesale/register/page.tsx:214
|
||
|
||
src/app/wholesale/register/page.tsx:225
|
||
|
||
src/app/wholesale/register/page.tsx:236
|
||
|
||
src/app/wholesale/register/page.tsx:249
|
||
|
||
src/components/admin/AIProviderPanel.tsx:233
|
||
|
||
src/components/admin/AIProviderPanel.tsx:254
|
||
|
||
src/components/admin/AIProviderPanel.tsx:283
|
||
|
||
src/components/admin/AIProviderPanel.tsx:297
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:114
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:119
|
||
|
||
src/components/admin/AddLocationModal.tsx:122
|
||
|
||
src/components/admin/AddLocationModal.tsx:137
|
||
|
||
src/components/admin/AddLocationModal.tsx:152
|
||
|
||
src/components/admin/AddLocationModal.tsx:165
|
||
|
||
src/components/admin/AddLocationModal.tsx:179
|
||
|
||
src/components/admin/AddLocationModal.tsx:195
|
||
|
||
src/components/admin/AddLocationModal.tsx:208
|
||
|
||
src/components/admin/AddLocationModal.tsx:223
|
||
|
||
src/components/admin/AddLocationModal.tsx:237
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:635-636
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:698-699
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:1005
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:1019
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:150
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:204
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:246
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:320
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:330
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:394
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:421
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:450
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:466
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:200
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:222
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:236
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:294
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:309
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:331
|
||
|
||
src/components/admin/AdvancedShipping.tsx:124
|
||
|
||
src/components/admin/AdvancedShipping.tsx:137
|
||
|
||
src/components/admin/AdvancedShipping.tsx:202
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:100
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:110
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:120
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:174
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:493
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:499
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:512
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:518
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:531
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:537
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:550
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:556
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:707
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:775
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:914
|
||
|
||
src/components/admin/CampaignListPanel.tsx:152
|
||
|
||
src/components/admin/CampaignListPanel.tsx:285
|
||
|
||
src/components/admin/CampaignListPanel.tsx:483
|
||
|
||
src/components/admin/CampaignListPanel.tsx:564
|
||
|
||
src/components/admin/CampaignListPanel.tsx:574
|
||
|
||
src/components/admin/CampaignListPanel.tsx:583
|
||
|
||
src/components/admin/CampaignListPanel.tsx:617
|
||
|
||
src/components/admin/CampaignListPanel.tsx:627
|
||
|
||
src/components/admin/CampaignListPanel.tsx:663
|
||
|
||
src/components/admin/ContactListPanel.tsx:102-118
|
||
|
||
src/components/admin/ContactListPanel.tsx:243
|
||
|
||
src/components/admin/ContactListPanel.tsx:282
|
||
|
||
src/components/admin/ContactListPanel.tsx:307
|
||
|
||
src/components/admin/CreateUserModal.tsx:294
|
||
|
||
src/components/admin/DriverPickupPanel.tsx:177
|
||
|
||
src/components/admin/EditLocationModal.tsx:141
|
||
|
||
src/components/admin/EditLocationModal.tsx:155
|
||
|
||
src/components/admin/EditLocationModal.tsx:169
|
||
|
||
src/components/admin/EditLocationModal.tsx:181
|
||
|
||
src/components/admin/EditLocationModal.tsx:194
|
||
|
||
src/components/admin/EditLocationModal.tsx:209
|
||
|
||
src/components/admin/EditLocationModal.tsx:221
|
||
|
||
src/components/admin/EditLocationModal.tsx:235
|
||
|
||
src/components/admin/EditLocationModal.tsx:248
|
||
|
||
src/components/admin/ElegantModal.tsx:68
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:504
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:516
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:570
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:776
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:331
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:340
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:370
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:386
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:400
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:426
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:441
|
||
|
||
src/components/admin/HarvestReach/SegmentEditModal.tsx:78
|
||
|
||
src/components/admin/HarvestReach/SegmentEditModal.tsx:92
|
||
|
||
src/components/admin/IntegrationsInner.tsx:228
|
||
|
||
src/components/admin/LocationsTab.tsx:224
|
||
|
||
src/components/admin/LocationsTab.tsx:333
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:196
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:210
|
||
|
||
src/components/admin/MessageLogPanel.tsx:132-148
|
||
|
||
src/components/admin/MessageLogPanel.tsx:322
|
||
|
||
src/components/admin/NewProductForm.tsx:277
|
||
|
||
src/components/admin/NewStopForm.tsx:131
|
||
|
||
src/components/admin/NewStopForm.tsx:156
|
||
|
||
src/components/admin/NewStopForm.tsx:182
|
||
|
||
src/components/admin/NewStopForm.tsx:208
|
||
|
||
src/components/admin/NewStopForm.tsx:232
|
||
|
||
src/components/admin/NewStopForm.tsx:296
|
||
|
||
src/components/admin/NewStopForm.tsx:307
|
||
|
||
src/components/admin/NewStopForm.tsx:321
|
||
|
||
src/components/admin/OrderEditForm.tsx:268
|
||
|
||
src/components/admin/OrderEditForm.tsx:287
|
||
|
||
src/components/admin/OrderEditForm.tsx:316
|
||
|
||
src/components/admin/OrderEditForm.tsx:336
|
||
|
||
src/components/admin/OrderEditForm.tsx:358
|
||
|
||
src/components/admin/OrderEditForm.tsx:399
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:206
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:280
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:304
|
||
|
||
src/components/admin/ProductEditForm.tsx:290
|
||
|
||
src/components/admin/ProductFilterBar.tsx:25
|
||
|
||
src/components/admin/ProductFormModal.tsx:415
|
||
|
||
src/components/admin/ProductTableBody.tsx:72
|
||
|
||
src/components/admin/ProductTableBody.tsx:175
|
||
|
||
src/components/admin/ProductTableClient.tsx:55
|
||
|
||
src/components/admin/ProductTableClient.tsx:99
|
||
|
||
src/components/admin/ProductTableClient.tsx:220
|
||
|
||
src/components/admin/ProductsClient.tsx:435
|
||
|
||
src/components/admin/ProductsClient.tsx:684
|
||
|
||
src/components/admin/ReportsDashboard.tsx:345
|
||
|
||
src/components/admin/ReportsDashboard.tsx:352
|
||
|
||
src/components/admin/ReportsDashboard.tsx:672
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:190
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:249
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:254-256
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:262-263
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:269-270
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:276-277
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:283-284
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:290-291
|
||
|
||
src/components/admin/SettingsSections.tsx:325
|
||
|
||
src/components/admin/SettingsSections.tsx:334
|
||
|
||
src/components/admin/SettingsSections.tsx:343
|
||
|
||
src/components/admin/SettingsSections.tsx:399
|
||
|
||
src/components/admin/SettingsSections.tsx:410
|
||
|
||
src/components/admin/SettingsSections.tsx:422
|
||
|
||
src/components/admin/SettingsSections.tsx:433
|
||
|
||
src/components/admin/SettingsSections.tsx:607
|
||
|
||
src/components/admin/SettingsSections.tsx:624
|
||
|
||
src/components/admin/SettingsSections.tsx:679
|
||
|
||
src/components/admin/SettingsSections.tsx:689
|
||
|
||
src/components/admin/SettingsSections.tsx:695
|
||
|
||
src/components/admin/SettingsSections.tsx:711
|
||
|
||
src/components/admin/ShippingFulfillmentPanel.tsx:509
|
||
|
||
src/components/admin/StopEditForm.tsx:124
|
||
|
||
src/components/admin/StopEditForm.tsx:149
|
||
|
||
src/components/admin/StopEditForm.tsx:176
|
||
|
||
src/components/admin/StopEditForm.tsx:198
|
||
|
||
src/components/admin/StopEditForm.tsx:210
|
||
|
||
src/components/admin/StopEditForm.tsx:222
|
||
|
||
src/components/admin/StopEditForm.tsx:233
|
||
|
||
src/components/admin/StopEditForm.tsx:248
|
||
|
||
src/components/admin/StopMessagingForm.tsx:171
|
||
|
||
src/components/admin/StopProductAssignment.tsx:235
|
||
|
||
src/components/admin/StopTableClient.tsx:548
|
||
|
||
src/components/admin/StopTableClient.tsx:1055
|
||
|
||
src/components/admin/TaxDashboard.tsx:267
|
||
|
||
src/components/admin/TaxDashboard.tsx:274
|
||
|
||
src/components/admin/TemplateEditForm.tsx:171
|
||
|
||
src/components/admin/TemplateEditForm.tsx:267
|
||
|
||
src/components/admin/TemplateEditForm.tsx:449
|
||
|
||
src/components/admin/TemplateEditForm.tsx:491
|
||
|
||
src/components/admin/TemplateEditForm.tsx:552
|
||
|
||
src/components/admin/TemplateEditForm.tsx:562
|
||
|
||
src/components/admin/TemplateEditForm.tsx:575
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:420
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:429
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:553
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:603
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:655
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:664
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:802
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:887
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:891
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:376-379
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:534
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:543
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:552
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:581
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:591
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:601
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:615
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:634
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:683
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:742
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:748
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:764
|
||
|
||
src/components/admin/UsersPage.tsx:370
|
||
|
||
src/components/admin/UsersPage.tsx:388
|
||
|
||
src/components/admin/UsersPage.tsx:520
|
||
|
||
src/components/admin/UsersPage.tsx:543
|
||
|
||
src/components/admin/UsersPage.tsx:558
|
||
|
||
src/components/admin/UsersPage.tsx:573
|
||
|
||
src/components/admin/UsersPage.tsx:586
|
||
|
||
src/components/admin/UsersPage.tsx:646
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:848
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:1261
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:91
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:94
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:99
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:40
|
||
|
||
src/components/admin/design-system/AdminFilterBar.tsx:52
|
||
|
||
src/components/admin/design-system/AdminFilterBar.tsx:90
|
||
|
||
src/components/admin/design-system/AdminFilterBar.tsx:102
|
||
|
||
src/components/admin/design-system/AdminModal.tsx:52
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:20
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:68
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:101
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:110
|
||
|
||
src/components/admin/design-system/AdminToggle.tsx:83
|
||
|
||
src/components/admin/shared/DataTable.tsx:100
|
||
|
||
src/components/admin/shared/DataTable.tsx:109
|
||
|
||
src/components/admin/shared/FilterBar.tsx:47
|
||
|
||
src/components/admin/stops/StopsLocations.tsx:186
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:111
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:129
|
||
|
||
src/components/notifications/ToastNotification.tsx:110
|
||
|
||
src/components/route-trace/AdminLookupPage.tsx:94
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:281
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:300
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:311
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:384
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:98
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:109
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:121
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:136
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:148
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:158
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:176
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:189
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:214
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:232
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:242
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:254
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:265
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:287
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:121
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:150
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:166
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:183
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:203
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:220
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:235
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:258
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:276
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:307
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:330
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:345
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:362
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:378
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:408
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:773
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:783
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:824
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:835
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:878
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:889
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:900
|
||
|
||
src/components/route-trace/LotListTable.tsx:215
|
||
|
||
src/components/route-trace/LotListTable.tsx:300-301
|
||
|
||
src/components/route-trace/LotListTable.tsx:314
|
||
|
||
src/components/route-trace/LotListTable.tsx:321-322
|
||
|
||
src/components/route-trace/QRScanModal.tsx:241
|
||
|
||
src/components/route-trace/QRScanModal.tsx:277
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:85
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:100
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:112
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:126
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:138
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:152
|
||
|
||
src/components/route-trace/RouteTraceDashboard.tsx:630
|
||
|
||
src/components/route-trace/RouteTraceSettings.tsx:69
|
||
|
||
src/components/route-trace/RouteTraceSettings.tsx:95
|
||
|
||
src/components/route-trace/RouteTraceSettings.tsx:121
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:93
|
||
|
||
src/components/storefront/HeroSection.tsx:91
|
||
|
||
src/components/storefront/IndianRiverPaginatedStops.tsx:115
|
||
|
||
src/components/storefront/PaginatedStops.tsx:116
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:173
|
||
|
||
src/components/storefront/ZipCodeSearch.tsx:51
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:772
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:787
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:920
|
||
|
||
src/components/water/WaterAdminClient.tsx:495
|
||
|
||
src/components/water/WaterAdminClient.tsx:596
|
||
|
||
src/components/water/WaterAdminClient.tsx:678
|
||
|
||
src/components/water/WaterAdminClient.tsx:684
|
||
|
||
src/components/water/WaterAdminClient.tsx:733-738
|
||
|
||
src/components/water/WaterFieldClient.tsx:455
|
||
|
||
src/components/water/WaterFieldClient.tsx:606
|
||
|
||
src/components/water/WaterFieldClient.tsx:696
|
||
|
||
src/components/wholesale/DepositModal.tsx:59
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:40
|
||
|
||
src/components/wholesale/admin/AddRecipientForm.tsx:29
|
||
|
||
src/components/wholesale/admin/AddRecipientForm.tsx:36
|
||
|
||
src/components/wholesale/admin/CustomerPricingPanel.tsx:55
|
||
|
||
src/components/wholesale/admin/CustomerPricingPanel.tsx:73
|
||
|
||
src/components/wholesale/admin/CustomerPricingPanel.tsx:87
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:247
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:371-372
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:383
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:403-404
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:425
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:433
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:224
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:229
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:295-296
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:314-315
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:362
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:374
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:468
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:502
|
||
|
||
src/components/wholesale/admin/PriceSheetModal.tsx:40
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:155
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:160
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:167
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:192
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:224
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:125
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:138
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:163
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:174
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:179
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:184
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:189
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:194
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:199
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:204
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:209
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:214
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:239
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:249
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:254
|
||
|
||
src/components/wholesale/admin/WebhookSettingsSection.tsx:108
|
||
|
||
src/components/wholesale/admin/WebhookSettingsSection.tsx:118
|
||
|
||
src/components/wholesale/admin/WebhookSettingsSection.tsx:131
|
||
|
||
⚠ Bugs: Data fetching inside an effect ×3
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-fetch-in-effect
|
||
fetch() inside useEffect can race, double-fire, or leak.
|
||
Use a data-fetching layer or Server Component instead.
|
||
→ Use a data-fetching layer or Server Component so fetches
|
||
do not race, double-fire, or leak from `useEffect`.
|
||
|
||
src/app/logout/page.tsx:9
|
||
|
||
src/components/admin/AIProviderPanel.tsx:110
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:206
|
||
|
||
⚠ Accessibility: outline:none removes focus ring ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-outline-none
|
||
Your keyboard users can't tell where they are because
|
||
outline: none hides the focus ring, so style :focus-visible
|
||
instead, or add a box-shadow focus ring.
|
||
→ Style `:focus-visible { outline: 2px solid
|
||
var(--color-accent); outline-offset: 2px }` so the focus
|
||
ring shows for keyboard users but not mouse clicks.
|
||
|
||
src/components/admin/CommandPalette.tsx:344
|
||
|
||
src/components/admin/stops/StopsDatePicker.tsx:61
|
||
|
||
⚠ Performance: sort() to find min or max ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/js-min-max-loop
|
||
This is slow because array.sort()[0] sorts the whole list
|
||
just to grab the smallest or largest, so use
|
||
Math.min(...array) instead
|
||
→ Use `Math.min(...array)` or `Math.max(...array)` instead
|
||
of sorting the whole list just to read the first or last
|
||
item
|
||
|
||
src/actions/ai-import.ts:266
|
||
|
||
src/components/admin/HarvestReach/AnalyticsDashboard.tsx:223
|
||
|
||
⚠ Bugs: Plain anchor reloads internal Next.js links ×36
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/nextjs-no-a-element
|
||
Plain <a> reloads the whole page for internal links, so
|
||
Next.js loses client-side navigation and prefetching.
|
||
→ `import Link from 'next/link'` for client-side
|
||
navigation, prefetching, and preserved scroll position
|
||
|
||
src/app/admin/communications/abandoned-carts/page.tsx:27-29
|
||
|
||
src/app/admin/communications/settings/page.tsx:24
|
||
|
||
src/app/admin/communications/welcome-sequence/page.tsx:26-28
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1830-1832
|
||
|
||
src/app/admin/settings/billing/BillingClientPage.tsx:501
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClientPage.tsx:413
|
||
|
||
src/app/brands/page.tsx:217-219
|
||
|
||
src/app/changelog/page.tsx:195
|
||
|
||
src/app/changelog/page.tsx:201
|
||
|
||
src/app/login/LoginClient.tsx:203
|
||
|
||
src/app/protected-example/page.tsx:36
|
||
|
||
src/app/protected-example/page.tsx:96
|
||
|
||
src/app/tuxedo/page.tsx:692
|
||
|
||
src/app/tuxedo/page.tsx:725
|
||
|
||
src/app/tuxedo/stops/TuxedoStopsList.tsx:75
|
||
|
||
src/app/waitlist/page.tsx:124-125
|
||
|
||
src/components/admin/CampaignListPanel.tsx:699
|
||
|
||
src/components/admin/DashboardClient.tsx:181
|
||
|
||
src/components/admin/DashboardHeader.tsx:36
|
||
|
||
src/components/admin/IntegrationsInner.tsx:311
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:319
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:382
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:320
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:85
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:95
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:175
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:185
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:167-169
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx:200
|
||
|
||
⚠ Bugs: Plain img ships unoptimized images ×6
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/nextjs-no-img-element
|
||
Plain <img> ships unoptimized, oversized images.
|
||
→ Use `next/image` so users get optimized formats,
|
||
responsive srcsets, and lazy loading instead of oversized
|
||
image downloads.
|
||
|
||
src/app/admin/v2/products/page.tsx:192
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:328
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:521
|
||
|
||
src/app/indian-river-direct/about/page.tsx:116
|
||
|
||
src/app/tuxedo/about/AboutClient.tsx:112
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:249
|
||
|
||
⚠ Bugs: Effect re-subscribes on a changing callback ×7
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/prefer-use-effect-event
|
||
Your effect re-subscribes whenever "closeMobileMenu"
|
||
changes, even though it's only used inside
|
||
`addEventListener`.
|
||
→ Wrap the callback with `useEffectEvent(callback)` (React
|
||
19+) and call it inside the sub-handler. An Effect Event
|
||
always sees the latest props and state but isn't a
|
||
dependency, so the effect won't re-subscribe every time the
|
||
parent redraws. See
|
||
https://react.dev/reference/react/useEffectEvent
|
||
|
||
src/components/admin/AdminSidebar.tsx:219
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:405
|
||
|
||
src/components/admin/HarvestReach/MatchingCustomersPanel.tsx:72
|
||
|
||
src/components/admin/ProductFormModal.tsx:164
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:119
|
||
|
||
src/components/route-trace/QRScanModal.tsx:179
|
||
|
||
src/components/storefront/QuickCartSheet.tsx:64
|
||
|
||
⚠ Bugs: Derived value copied into state ×34
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-derived-state
|
||
Storing "dirty" in state when you can derive it from other
|
||
values costs an extra render.
|
||
→ Work out the value while rendering (or with useMemo if
|
||
it's expensive) instead of copying it into useState through
|
||
a useEffect. See
|
||
https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClientPage.tsx:127
|
||
|
||
src/components/admin/AddStopModal.tsx:52-59
|
||
|
||
src/components/admin/CommandPalette.tsx:226
|
||
|
||
src/components/admin/EditLocationModal.tsx:47-55
|
||
|
||
src/components/admin/EditStopModal.tsx:65-73
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:106
|
||
|
||
src/components/admin/ReportsDashboard.tsx:313
|
||
|
||
src/components/admin/SettingsSections.tsx:167
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:74
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:200
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:167
|
||
|
||
⚠ Bugs: Multiple setState calls in one effect ×11
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-cascading-set-state
|
||
4 setState calls in one useEffect redraw your screen each
|
||
time they run together.
|
||
→ Combine related updates in `useReducer` so one effect
|
||
does not redraw the screen once per `setState` call.
|
||
|
||
src/app/cart/CartClient.tsx:46
|
||
|
||
src/app/wholesale/employee/page.tsx:44
|
||
|
||
src/components/admin/AddStopModal.tsx:49
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:78
|
||
|
||
src/components/admin/EditLocationModal.tsx:44
|
||
|
||
src/components/admin/EditStopModal.tsx:55
|
||
|
||
src/components/admin/HarvestReach/MatchingCustomersPanel.tsx:53
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:33
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:79
|
||
|
||
src/components/admin/StopDetailModal.tsx:37
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:37
|
||
|
||
⚠ Bugs: preventDefault on a form or link ×3
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-prevent-default
|
||
Your users can't submit this <form> without JavaScript
|
||
because onSubmit calls preventDefault(), so use a server
|
||
action like `<form action={serverAction}>` to make it work
|
||
either way.
|
||
→ Use `<form action>` where your framework supports it (it
|
||
works without JS), or use a `<button>` instead of an `<a>`
|
||
with preventDefault.
|
||
|
||
src/app/indian-river-direct/page.tsx:456
|
||
|
||
src/app/login/LoginClient.tsx:136
|
||
|
||
src/components/storefront/StorefrontFooter.tsx:53
|
||
|
||
⚠ Bugs: next/image fill image is missing sizes ×15
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/nextjs-image-missing-sizes
|
||
next/image uses fill without sizes, so your users download
|
||
the largest image.
|
||
→ Add `sizes` matching your layout so `next/image` does not
|
||
assume the largest candidate and make users download
|
||
oversized images.
|
||
|
||
src/components/admin/ProductFormModal.tsx:367
|
||
|
||
src/components/admin/ProductTableClient.tsx:159
|
||
|
||
src/components/admin/ProductsClient.tsx:457
|
||
|
||
src/components/admin/ProductsClient.tsx:618
|
||
|
||
src/components/storefront/CinematicShowcase.tsx:69
|
||
|
||
src/components/storefront/ProductCard.tsx:202
|
||
|
||
src/components/storefront/StorefrontFooter.tsx:82
|
||
|
||
src/components/storefront/StorefrontFooter.tsx:86
|
||
|
||
src/components/storefront/StorefrontHeader.tsx:81
|
||
|
||
src/components/storefront/StorefrontHeader.tsx:85
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:252
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:388
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:654
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:910
|
||
|
||
src/components/water/WaterFieldClient.tsx:669
|
||
|
||
⚠ Accessibility: Anchor used as a button
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/anchor-is-valid
|
||
Keyboard users can't reach this link because its `href`
|
||
goes nowhere (`#`, `javascript:`, or empty), so point it at
|
||
a real destination.
|
||
→ Give links a real destination. Use `<button>` for in-page
|
||
actions.
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:29
|
||
|
||
⚠ Bugs: Live state pushed to parent via effect
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-pass-live-state-to-parent
|
||
Pushing state up to a parent from a useEffect costs your
|
||
users an extra render.
|
||
→ Move the state up to the parent (or return it from the
|
||
hook), instead of handing it back up through a prop
|
||
callback in a useEffect. See
|
||
https://react.dev/learn/you-might-not-need-an-effect#notifying-parent-components-about-state-changes
|
||
|
||
src/components/route-trace/QRScanModal.tsx:172
|
||
|
||
⚠ Maintainability: deslop/unused-file ×114
|
||
Unused file is not reachable from any entry point, so it
|
||
adds maintenance surface without shipping any code.
|
||
→ Delete the file if it is truly unreachable, or import it
|
||
from an entry point.
|
||
|
||
db/schema/audit.ts
|
||
|
||
src/actions/admin/audit.ts
|
||
|
||
src/actions/integrations/credentials.ts
|
||
|
||
src/actions/locations.ts
|
||
|
||
src/actions/orders/create-admin-order.ts
|
||
|
||
src/actions/reports.ts
|
||
|
||
src/actions/route-trace/types.ts
|
||
|
||
src/actions/settings/features.ts
|
||
|
||
src/actions/shipping/settings.ts
|
||
|
||
src/actions/square-inventory.ts
|
||
|
||
src/actions/stops/get-stop-customers.ts
|
||
|
||
src/actions/stops/get-stop-details.ts
|
||
|
||
src/actions/stripe-connect.ts
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx
|
||
|
||
src/app/admin/settings/billing/AddAddonButton.tsx
|
||
|
||
src/app/admin/settings/billing/AddPaymentMethodButton.tsx
|
||
|
||
src/app/admin/settings/billing/BillingClient.tsx
|
||
|
||
src/app/admin/settings/billing/BillingClientPage.tsx
|
||
|
||
src/app/admin/settings/billing/BillingCycleToggle.tsx
|
||
|
||
src/app/admin/settings/billing/PlanUpgradeButton.tsx
|
||
|
||
src/app/admin/settings/billing/RemoveAddonButton.tsx
|
||
|
||
src/app/admin/settings/billing/StripePortalButton.tsx
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClientPage.tsx
|
||
|
||
src/app/change-password/ChangePasswordForm.tsx
|
||
|
||
src/components/admin/AIProviderPanel.tsx
|
||
|
||
src/components/admin/AddLocationModal.tsx
|
||
|
||
src/components/admin/AddStopModal.tsx
|
||
|
||
src/components/admin/AdminHeader.tsx
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx
|
||
|
||
src/components/admin/AdminStopsPanel.tsx
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx
|
||
|
||
src/components/admin/AdvancedPayments.tsx
|
||
|
||
src/components/admin/AdvancedSettingsClient.tsx
|
||
|
||
src/components/admin/AdvancedShipping.tsx
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx
|
||
|
||
src/components/admin/BrandFeatureCards.tsx
|
||
|
||
src/components/admin/CartHydration.tsx
|
||
|
||
src/components/admin/CommunicationsLoading.tsx
|
||
|
||
src/components/admin/CommunicationsNav.tsx
|
||
|
||
src/components/admin/DashboardHeader.tsx
|
||
|
||
src/components/admin/DashboardUpgradeButton.tsx
|
||
|
||
src/components/admin/EditLocationModal.tsx
|
||
|
||
src/components/admin/ElegantModal.tsx
|
||
|
||
src/components/admin/HarvestReach/HarvestReachNav.tsx
|
||
|
||
src/components/admin/IntegrationsInner.tsx
|
||
|
||
src/components/admin/LocationsTab.tsx
|
||
|
||
src/components/admin/OrderTableBody.tsx
|
||
|
||
src/components/admin/ProductAssignmentForm.tsx
|
||
|
||
src/components/admin/ProductEditForm.tsx
|
||
|
||
src/components/admin/ProductFilterBar.tsx
|
||
|
||
src/components/admin/ProductSyncBanner.tsx
|
||
|
||
src/components/admin/ProductTableBody.tsx
|
||
|
||
src/components/admin/ProductTableClient.tsx
|
||
|
||
src/components/admin/ReportsDashboard.tsx
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx
|
||
|
||
src/components/admin/SquareSyncWidget.tsx
|
||
|
||
src/components/admin/SquareSyncWidgetWrapper.tsx
|
||
|
||
src/components/admin/StatsStrip.tsx
|
||
|
||
src/components/admin/StopDetailModal.tsx
|
||
|
||
src/components/admin/StopMessagingForm.tsx
|
||
|
||
src/components/admin/StopTableBody.tsx
|
||
|
||
src/components/admin/StopsCalendarClient.tsx
|
||
|
||
src/components/admin/StopsHeaderActions.tsx
|
||
|
||
src/components/admin/StopsLocationsTabs.tsx
|
||
|
||
src/components/admin/StopsViewClient.tsx
|
||
|
||
src/components/admin/TabSwitcher.tsx
|
||
|
||
src/components/admin/TaxDashboard.tsx
|
||
|
||
src/components/admin/TaxQuarterlySummary.tsx
|
||
|
||
src/components/admin/design-system/AdminModal.tsx
|
||
|
||
src/components/admin/design-system/ToastExport.ts
|
||
|
||
src/components/admin/shared/DataTable.tsx
|
||
|
||
src/components/admin/shared/FilterBar.tsx
|
||
|
||
src/components/admin/shared/PageHeader.tsx
|
||
|
||
src/components/admin/shared/StatusBadge.tsx
|
||
|
||
src/components/admin/shared/index.ts
|
||
|
||
src/components/admin/stops/StopsCalendar.tsx
|
||
|
||
src/components/admin/stops/StopsDashboardClient.tsx
|
||
|
||
src/components/admin/stops/StopsList.tsx
|
||
|
||
src/components/admin/stops/StopsLocations.tsx
|
||
|
||
src/components/admin/stops/types.ts
|
||
|
||
src/components/changelog/ChangelogFeed.tsx
|
||
|
||
src/components/landing/FeaturesAndStats.tsx
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx
|
||
|
||
src/components/providers/AnalyticsProvider.tsx
|
||
|
||
src/components/providers/ErrorBoundary.tsx
|
||
|
||
src/components/referral/ReferralSystem.tsx
|
||
|
||
src/components/route-trace/LotCreateForm.tsx
|
||
|
||
src/components/route-trace/PublicTraceActions.tsx
|
||
|
||
src/components/shared/EmptyState.tsx
|
||
|
||
src/components/shared/LoadingSkeleton.tsx
|
||
|
||
src/components/shared/SectionHeader.tsx
|
||
|
||
src/components/shared/ThemeToggle.tsx
|
||
|
||
src/components/storefront/BreadcrumbNav.tsx
|
||
|
||
src/components/storefront/HeroSection.tsx
|
||
|
||
src/components/storefront/IndianRiverGrainOverlay.tsx
|
||
|
||
src/components/storefront/IndianRiverPaginatedStops.tsx
|
||
|
||
src/components/storefront/ZipCodeSearch.tsx
|
||
|
||
src/config/brands.ts
|
||
|
||
src/lib/auth-guards.ts
|
||
|
||
src/lib/billing.ts
|
||
|
||
src/lib/data-service.ts
|
||
|
||
src/lib/date-utils.ts
|
||
|
||
src/lib/error-handler.ts
|
||
|
||
src/lib/fedex-auth.ts
|
||
|
||
src/lib/reports-export.ts
|
||
|
||
src/lib/route-trace-data.ts
|
||
|
||
src/lib/route-trace-units.ts
|
||
|
||
src/lib/seo.ts
|
||
|
||
src/lib/svc-headers.ts
|
||
|
||
src/lib/validation.ts
|
||
|
||
⚠ Performance: Array lookup inside a loop ×11
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/js-set-map-lookups
|
||
This scales poorly because `array.includes()` inside a loop
|
||
scans the whole list every time. Use a Set for
|
||
constant-time lookups.
|
||
→ Use a `Set` or `Map` when you check for the same items
|
||
over and over. `Array.includes`/`find` scans the whole list
|
||
each time
|
||
|
||
src/actions/ai-import.ts:261
|
||
|
||
src/actions/ai-import.ts:304
|
||
|
||
src/actions/shipping/fedex-rates.ts:291
|
||
|
||
src/actions/square-orders.ts:106
|
||
|
||
src/components/admin/ContactImportForm.tsx:232
|
||
|
||
src/lib/column-detector.ts:180
|
||
|
||
src/lib/column-detector.ts:228
|
||
|
||
src/lib/csv-parsers.ts:31
|
||
|
||
src/lib/csv-parsers.ts:63
|
||
|
||
src/lib/csv-parsers.ts:131
|
||
|
||
src/lib/csv-parsers.ts:220
|
||
|
||
⚠ Accessibility: Interaction on static element ×43
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-static-element-interactions
|
||
Screen reader users can't tell this click handler is
|
||
interactive because it has no `role`, so add a `role` or
|
||
use a button or link.
|
||
→ Give clickable static elements a `role`, or use a button
|
||
or link.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:178
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:612
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:365
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:498
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:194
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:448
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:257
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:283
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:882
|
||
|
||
src/components/admin/CampaignListPanel.tsx:114
|
||
|
||
src/components/admin/ElegantModal.tsx:36
|
||
|
||
src/components/admin/GlassModal.tsx:48
|
||
|
||
src/components/admin/HarvestReach/SegmentEditModal.tsx:44
|
||
|
||
src/components/admin/HarvestReach/SegmentListSidebar.tsx:91
|
||
|
||
src/components/admin/NewProductForm.tsx:243
|
||
|
||
src/components/admin/ProductEditForm.tsx:256
|
||
|
||
src/components/admin/ProductFormModal.tsx:244
|
||
|
||
src/components/admin/ProductFormModal.tsx:322
|
||
|
||
src/components/admin/ProductTableBody.tsx:189
|
||
|
||
src/components/admin/ProductTableBody.tsx:206
|
||
|
||
src/components/admin/ProductTableClient.tsx:234
|
||
|
||
src/components/admin/ProductTableClient.tsx:251
|
||
|
||
src/components/admin/ProductsClient.tsx:536
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:165
|
||
|
||
src/components/admin/StopTableClient.tsx:861
|
||
|
||
src/components/admin/StopTableClient.tsx:915
|
||
|
||
src/components/admin/TemplateEditForm.tsx:133
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:149
|
||
|
||
src/components/admin/UsersPage.tsx:432
|
||
|
||
src/components/admin/UsersPage.tsx:511
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:51
|
||
|
||
src/components/admin/design-system/AdminModal.tsx:28
|
||
|
||
src/components/cart/CartRestoredToast.tsx:25
|
||
|
||
src/components/changelog/ChangelogFeed.tsx:79
|
||
|
||
src/components/landing/HeroSection.tsx:564
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx:174
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:288
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:232
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:93
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:86
|
||
|
||
src/components/wholesale/DepositModal.tsx:43
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:32
|
||
|
||
src/components/wholesale/admin/PriceSheetModal.tsx:31
|
||
|
||
⚠ Accessibility: Role used instead of HTML tag ×21
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/prefer-tag-over-role
|
||
Screen reader users get more reliable semantics from
|
||
`<output>` than `role="status"`, so use `<output>` instead.
|
||
→ Use the matching HTML element when one exists so browsers
|
||
and assistive tech get native semantics.
|
||
|
||
src/app/cart/CartClient.tsx:129
|
||
|
||
src/app/cart/CartClient.tsx:148
|
||
|
||
src/app/cart/CartClient.tsx:187
|
||
|
||
src/app/cart/CartClient.tsx:206
|
||
|
||
src/app/cart/CartClient.tsx:214
|
||
|
||
src/app/cart/CartClient.tsx:271
|
||
|
||
src/app/contact/ContactClientPage.tsx:121
|
||
|
||
src/app/pricing/PricingClientPage.tsx:388
|
||
|
||
src/components/admin/BrandSelector.tsx:144
|
||
|
||
src/components/admin/CommandPalette.tsx:262
|
||
|
||
src/components/admin/CommandPalette.tsx:356
|
||
|
||
src/components/admin/LoadingState.tsx:32
|
||
|
||
src/components/admin/OfflineBanner.tsx:35
|
||
|
||
src/components/admin/ProductFormModal.tsx:256
|
||
|
||
src/components/admin/ProductsClient.tsx:541
|
||
|
||
src/components/admin/StopsCalendarClient.tsx:323-325
|
||
|
||
src/components/admin/StopsCalendarClient.tsx:346
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:909
|
||
|
||
src/components/admin/products/StockAdjustButton.tsx:79
|
||
|
||
src/components/transitions/RouteAnnouncer.tsx:30
|
||
|
||
⚠ Performance: Full Framer Motion import ×36
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/use-lazy-motion
|
||
Importing "motion" ships about 30 kb of extra code and
|
||
slows page load. Use "m" with LazyMotion instead.
|
||
→ Use `import { LazyMotion, m } from "framer-motion"` with
|
||
`domAnimation` features. Saves about 30kb.
|
||
|
||
src/app/indian-river-direct/about/error.tsx:4
|
||
|
||
src/app/indian-river-direct/about/page.tsx:4
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:4
|
||
|
||
src/app/indian-river-direct/contact/error.tsx:4
|
||
|
||
src/app/indian-river-direct/error.tsx:4
|
||
|
||
src/app/indian-river-direct/faq/FAQClientPage.tsx:5
|
||
|
||
src/app/indian-river-direct/faq/error.tsx:4
|
||
|
||
src/app/indian-river-direct/page.tsx:6
|
||
|
||
src/app/indian-river-direct/stops/[id]/error.tsx:4
|
||
|
||
src/app/indian-river-direct/stops/[id]/page.tsx:6
|
||
|
||
src/app/tuxedo/about/AboutClient.tsx:4
|
||
|
||
src/app/tuxedo/about/error.tsx:4
|
||
|
||
src/app/tuxedo/contact/error.tsx:4
|
||
|
||
src/app/tuxedo/error.tsx:4
|
||
|
||
src/app/tuxedo/faq/error.tsx:4
|
||
|
||
src/app/tuxedo/page.tsx:5
|
||
|
||
src/app/tuxedo/stops/[id]/error.tsx:4
|
||
|
||
src/components/about/CTASection.tsx:4
|
||
|
||
src/components/about/ContactSection.tsx:3
|
||
|
||
src/components/about/FamilyTimelineSection.tsx:3
|
||
|
||
src/components/about/IndianRiverCTASection.tsx:4
|
||
|
||
src/components/about/IndianRiverCitrusSection.tsx:3
|
||
|
||
src/components/about/IndianRiverContactSection.tsx:3
|
||
|
||
src/components/about/IndianRiverMissionSection.tsx:3
|
||
|
||
src/components/about/IndianRiverTeamSection.tsx:3
|
||
|
||
src/components/about/IndianRiverValuesSection.tsx:3
|
||
|
||
src/components/about/MissionSection.tsx:3
|
||
|
||
src/components/admin/TabSwitcher.tsx:3
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:3
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:7
|
||
|
||
src/components/storefront/ProductCard.tsx:5
|
||
|
||
src/components/storefront/QuickCartSheet.tsx:5
|
||
|
||
src/components/storefront/StorefrontHeader.tsx:6
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:7
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:5
|
||
|
||
src/components/storefront/WhyIndianRiverDirect.tsx:4
|
||
|
||
⚠ Bugs: Client fetch for server data
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/nextjs-no-client-fetch-for-server-data
|
||
useEffect + fetch in a page/layout makes your users wait
|
||
through an extra round trip & loading spinner.
|
||
→ Remove 'use client' and fetch directly in the Server
|
||
Component. No API round-trip, and secrets stay on the
|
||
server.
|
||
|
||
src/app/logout/page.tsx:9
|
||
|
||
⚠ Bugs: All state reset on prop change
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-reset-all-state-on-prop-change
|
||
Your users briefly see stale state when a prop changes
|
||
because this useEffect clears all state.
|
||
→ Pass the prop as `key` so React resets the component for
|
||
you when the prop changes, instead of clearing every state
|
||
value by hand in a useEffect. See
|
||
https://react.dev/learn/you-might-not-need-an-effect#resetting-all-state-when-a-prop-changes
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:37
|
||
|
||
✖ Bugs: State synced to a prop inside an effect ×40
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-adjust-state-on-prop-change
|
||
This effect adjusts state after a prop changes, so users
|
||
briefly see the stale value.
|
||
→ Adjust the state inline during render with a `prev`-prop
|
||
comparison (`if (prop !== prevProp) { setPrevProp(prop);
|
||
setX(...); }`), or refactor to remove the duplicated state.
|
||
Routing the adjustment through a useEffect forces an extra
|
||
render with a stale UI between the two commits. See
|
||
https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes
|
||
|
||
src/components/admin/AddStopModal.tsx:60-61
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 59 | setCutoffTime(duplicateFrom?.cutoff_time ?? ""[0m… │
|
||
│ > 60 | setStatus("draft"); │
|
||
│ > 61 | setError(null); │
|
||
│ 62 | // Auto-focus city field for fast data entry │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:80
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 79 | if (!isPlatformAdmin) return; │
|
||
│ > 80 | setLoading(true); │
|
||
│ | ^ │
|
||
│ 81 | getBrandSettings(activeBrandId).then((result) =>[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/components/admin/EditLocationModal.tsx:56
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 55 | setNotes(location.notes ?? ""); │
|
||
│ > 56 | setError(null); │
|
||
│ | ^ │
|
||
│ 57 | } │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/components/admin/EditStopModal.tsx:76-86
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 75 | // Add mode - reset form │
|
||
│ > 76 | setCity(""); │
|
||
│ > 77 | setStateField(""); │
|
||
│ > 78 | setLocation(""); │
|
||
│ > 79 | setDate(""); │
|
||
│ > 80 | setTime(""); │
|
||
│ > 81 | setAddress(""); │
|
||
│ > 82 | setZip(""); │
|
||
│ > 83 | setCutoffTime(""); │
|
||
│ > 84 | setStatus("draft"); │
|
||
│ > 85 | } │
|
||
│ > 86 | setError(null); │
|
||
│ 87 | requestAnimationFrame(() => cityRef.current?.f[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/components/admin/HarvestReach/MatchingCustomersPanel.tsx:55-59
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 54 | if (rules.filters.length === 0) { │
|
||
│ > 55 | setPreview(null); │
|
||
│ > 56 | setCustomerCount(undefined); │
|
||
│ > 57 | return; │
|
||
│ > 58 | } │
|
||
│ > 59 | setLoading(true); │
|
||
│ 60 | clearTimeout(timerRef.current); │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:81-83
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 80 | if (!isPlatformAdmin) return; │
|
||
│ > 81 | setLoading(true); │
|
||
│ > 82 | setError(null); │
|
||
│ > 83 | setDirty(false); │
|
||
│ 84 | getShippingSettings(activeBrandId).then((result)[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/components/admin/StopDetailModal.tsx:39-40
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 38 | let cancelled = false; │
|
||
│ > 39 | setLoading(true); │
|
||
│ > 40 | setLoadError(null); │
|
||
│ 41 | getStopDetails(stopId) │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:94
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 93 | } else { │
|
||
│ > 94 | setIsVisible(false); │
|
||
│ | ^ │
|
||
│ 95 | } │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:39-55
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 38 | if (isOpen) { │
|
||
│ > 39 | setCropType(""); │
|
||
│ > 40 | setVariety(""); │
|
||
│ > 41 | setHarvestDate(new Date().toISOString().split([0m… │
|
||
│ > 42 | setFieldLocation(""); │
|
||
│ > 43 | setFieldBlock(""); │
|
||
│ > 44 | setWorkerName(""); │
|
||
│ > 45 | setPackerName(""); │
|
||
│ > 46 | setQuantityLbs(""); │
|
||
│ > 47 | setYieldEstimateLbs(""); │
|
||
│ > 48 | setYieldUnit("lbs"); │
|
||
│ > 49 | setCustomYieldUnit(""); │
|
||
│ > 50 | setBinId(""); │
|
||
│ > 51 | setContainerId(""); │
|
||
│ > 52 | setPallets(""); │
|
||
│ > 53 | setNotes(""); │
|
||
│ > 54 | setError(null); │
|
||
│ > 55 | setNotesOpen(false); │
|
||
│ 56 | } │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
⚠ Accessibility: Text is too small ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-tiny-text
|
||
Your users strain to read 11px text, so use at least 12px
|
||
for body text, & 16px is best.
|
||
→ Use at least 12px for body text, and 16px is best. Small
|
||
text is hard to read, especially on phones.
|
||
|
||
src/components/admin/CommandPalette.tsx:441
|
||
|
||
src/components/admin/CommandPalette.tsx:462
|
||
|
||
⚠ Bugs: Button missing explicit type ×527
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/button-has-type
|
||
Your users can submit the form by accident because a
|
||
`<button>` with no `type` defaults to submit.
|
||
→ Set an explicit button `type` so plain buttons do not
|
||
submit forms by accident: `type="button"`, `"submit"`, or
|
||
`"reset"`.
|
||
|
||
src/app/admin/error.tsx:63
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:204
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:212
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:268
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:367-370
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:397
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:409
|
||
|
||
src/app/admin/launch-checklist/page.tsx:111
|
||
|
||
src/app/admin/launch-checklist/page.tsx:162
|
||
|
||
src/app/admin/launch-checklist/page.tsx:190
|
||
|
||
src/app/admin/launch-checklist/page.tsx:211
|
||
|
||
src/app/admin/me/AdminMeClient.tsx:92
|
||
|
||
src/app/admin/products/import/page.tsx:96
|
||
|
||
src/app/admin/products/import/page.tsx:143
|
||
|
||
src/app/admin/products/import/page.tsx:172
|
||
|
||
src/app/admin/sales/import/page.tsx:116
|
||
|
||
src/app/admin/sales/import/page.tsx:139
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:99
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:116
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:125
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:197
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:374
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:424
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:528
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:611
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:729
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:766
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:884
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:908
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:918
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:957
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:966
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1030
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1121
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1143
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1244
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1261
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1404
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1417
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1485
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1540
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1638
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1674
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1683
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1742
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1773
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1861
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1870
|
||
|
||
src/app/admin/settings/billing/AddAddonButton.tsx:29
|
||
|
||
src/app/admin/settings/billing/AddPaymentMethodButton.tsx:27
|
||
|
||
src/app/admin/settings/billing/BillingClient.tsx:50
|
||
|
||
src/app/admin/settings/billing/BillingClientPage.tsx:227
|
||
|
||
src/app/admin/settings/billing/BillingClientPage.tsx:329
|
||
|
||
src/app/admin/settings/billing/BillingCycleToggle.tsx:21
|
||
|
||
src/app/admin/settings/billing/BillingCycleToggle.tsx:31
|
||
|
||
src/app/admin/settings/billing/PlanUpgradeButton.tsx:62
|
||
|
||
src/app/admin/settings/billing/RemoveAddonButton.tsx:28
|
||
|
||
src/app/admin/settings/billing/StripePortalButton.tsx:27
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:399
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:433
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:440
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:538
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:616
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:631
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:188
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:204
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:327
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:369
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:507
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:534
|
||
|
||
src/app/blog/page.tsx:224
|
||
|
||
src/app/cart/CartClient.tsx:116
|
||
|
||
src/app/cart/CartClient.tsx:159
|
||
|
||
src/app/cart/CartClient.tsx:223
|
||
|
||
src/app/cart/CartClient.tsx:234
|
||
|
||
src/app/cart/CartClient.tsx:272
|
||
|
||
src/app/cart/CartClient.tsx:278
|
||
|
||
src/app/cart/CartClient.tsx:289
|
||
|
||
src/app/cart/CartClient.tsx:329
|
||
|
||
src/app/cart/CartClient.tsx:339
|
||
|
||
src/app/cart/CartClient.tsx:364
|
||
|
||
src/app/contact/ContactClientPage.tsx:129
|
||
|
||
src/app/indian-river-direct/about/error.tsx:50
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:150
|
||
|
||
src/app/indian-river-direct/contact/error.tsx:50
|
||
|
||
src/app/indian-river-direct/error.tsx:59
|
||
|
||
src/app/indian-river-direct/faq/FAQClientPage.tsx:90
|
||
|
||
src/app/indian-river-direct/faq/FAQClientPage.tsx:179
|
||
|
||
src/app/indian-river-direct/faq/error.tsx:50
|
||
|
||
src/app/indian-river-direct/page.tsx:392
|
||
|
||
src/app/indian-river-direct/page.tsx:462
|
||
|
||
src/app/indian-river-direct/stops/[id]/error.tsx:50
|
||
|
||
src/app/pricing/PricingClientPage.tsx:164
|
||
|
||
src/app/pricing/PricingClientPage.tsx:179
|
||
|
||
src/app/pricing/PricingClientPage.tsx:318
|
||
|
||
src/app/pricing/PricingClientPage.tsx:389
|
||
|
||
src/app/pricing/PricingClientPage.tsx:400
|
||
|
||
src/app/roadmap/page.tsx:146
|
||
|
||
src/app/roadmap/page.tsx:174
|
||
|
||
src/app/tuxedo/about/error.tsx:45
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:119
|
||
|
||
src/app/tuxedo/contact/error.tsx:45
|
||
|
||
src/app/tuxedo/error.tsx:53
|
||
|
||
src/app/tuxedo/faq/FAQClientPage.tsx:109
|
||
|
||
src/app/tuxedo/faq/FAQClientPage.tsx:168
|
||
|
||
src/app/tuxedo/faq/error.tsx:45
|
||
|
||
src/app/tuxedo/stops/[id]/error.tsx:45
|
||
|
||
src/app/wholesale/employee/page.tsx:151
|
||
|
||
src/app/wholesale/employee/page.tsx:169
|
||
|
||
src/app/wholesale/employee/page.tsx:412
|
||
|
||
src/app/wholesale/employee/page.tsx:423
|
||
|
||
src/app/wholesale/employee/page.tsx:442
|
||
|
||
src/app/wholesale/employee/page.tsx:454
|
||
|
||
src/app/wholesale/employee/page.tsx:458
|
||
|
||
src/app/wholesale/employee/page.tsx:463
|
||
|
||
src/app/wholesale/portal/page.tsx:561
|
||
|
||
src/app/wholesale/portal/page.tsx:574
|
||
|
||
src/app/wholesale/portal/page.tsx:721
|
||
|
||
src/app/wholesale/portal/page.tsx:761
|
||
|
||
src/app/wholesale/portal/page.tsx:778
|
||
|
||
src/app/wholesale/portal/page.tsx:798
|
||
|
||
src/app/wholesale/portal/page.tsx:833
|
||
|
||
src/app/wholesale/portal/page.tsx:935
|
||
|
||
src/components/admin/AIProviderPanel.tsx:196
|
||
|
||
src/components/admin/AIProviderPanel.tsx:317
|
||
|
||
src/components/admin/AIProviderPanel.tsx:347
|
||
|
||
src/components/admin/AIProviderPanel.tsx:354
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:100
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:106
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:114
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:119
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:170-173
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:177
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:203
|
||
|
||
src/components/admin/AdminHeader.tsx:153
|
||
|
||
src/components/admin/AdminHeader.tsx:208
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:416
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:466
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:531
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:561
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:873
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:118
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:127
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:162
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:246
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:260
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:271
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:288
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:294
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:320
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:330
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:356
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:500
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:555
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:562
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:259
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:266
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:354
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:361
|
||
|
||
src/components/admin/AdvancedPayments.tsx:349
|
||
|
||
src/components/admin/AdvancedPayments.tsx:364
|
||
|
||
src/components/admin/AdvancedPayments.tsx:377
|
||
|
||
src/components/admin/AdvancedPayments.tsx:389
|
||
|
||
src/components/admin/AdvancedSettingsClient.tsx:90
|
||
|
||
src/components/admin/AdvancedSettingsClient.tsx:201
|
||
|
||
src/components/admin/AdvancedSettingsClient.tsx:205
|
||
|
||
src/components/admin/AdvancedShipping.tsx:166
|
||
|
||
src/components/admin/AdvancedShipping.tsx:173
|
||
|
||
src/components/admin/AdvancedShipping.tsx:202
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:140
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:146
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:174
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:75
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:81
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:87
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:93
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:420
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:440
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:446
|
||
|
||
src/components/admin/BrandFeatureCards.tsx:114
|
||
|
||
src/components/admin/BrandFeatureCards.tsx:167
|
||
|
||
src/components/admin/BrandFeatureCards.tsx:173
|
||
|
||
src/components/admin/CampaignListPanel.tsx:132
|
||
|
||
src/components/admin/CampaignListPanel.tsx:180
|
||
|
||
src/components/admin/CampaignListPanel.tsx:186
|
||
|
||
src/components/admin/CampaignListPanel.tsx:236
|
||
|
||
src/components/admin/ContactImportForm.tsx:517
|
||
|
||
src/components/admin/ContactImportForm.tsx:659
|
||
|
||
src/components/admin/ContactImportForm.tsx:665
|
||
|
||
src/components/admin/ContactImportForm.tsx:716
|
||
|
||
src/components/admin/ContactListPanel.tsx:355
|
||
|
||
src/components/admin/ContactListPanel.tsx:386
|
||
|
||
src/components/admin/ContactListPanel.tsx:423
|
||
|
||
src/components/admin/ContactListPanel.tsx:431
|
||
|
||
src/components/admin/CreateUserModal.tsx:270
|
||
|
||
src/components/admin/CreateUserModal.tsx:294
|
||
|
||
src/components/admin/CreateUserModal.tsx:440
|
||
|
||
src/components/admin/CreateUserModal.tsx:447
|
||
|
||
src/components/admin/DashboardHeader.tsx:40
|
||
|
||
src/components/admin/DashboardUpgradeButton.tsx:21
|
||
|
||
src/components/admin/DriverPickupPanel.tsx:215
|
||
|
||
src/components/admin/DriverPickupPanel.tsx:357
|
||
|
||
src/components/admin/ElegantModal.tsx:68
|
||
|
||
src/components/admin/GlassModal.tsx:106
|
||
|
||
src/components/admin/HarvestReach/AnalyticsDashboard.tsx:244
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:205
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:708
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPage.tsx:87
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:118
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:168
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:304
|
||
|
||
src/components/admin/HarvestReach/SegmentEditModal.tsx:66
|
||
|
||
src/components/admin/HarvestReach/SegmentListSidebar.tsx:105
|
||
|
||
src/components/admin/IntegrationsInner.tsx:263-264
|
||
|
||
src/components/admin/LocationsTab.tsx:209
|
||
|
||
src/components/admin/LocationsTab.tsx:333
|
||
|
||
src/components/admin/LocationsTab.tsx:342
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:152
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:175
|
||
|
||
src/components/admin/MessageLogPanel.tsx:453
|
||
|
||
src/components/admin/MessageLogPanel.tsx:463
|
||
|
||
src/components/admin/MessageLogPanel.tsx:476
|
||
|
||
src/components/admin/OrderEditForm.tsx:256
|
||
|
||
src/components/admin/OrderPickupAction.tsx:38
|
||
|
||
src/components/admin/ProductAssignmentForm.tsx:94
|
||
|
||
src/components/admin/ProductEditForm.tsx:210
|
||
|
||
src/components/admin/ProductEditForm.tsx:224
|
||
|
||
src/components/admin/ProductEditForm.tsx:317
|
||
|
||
src/components/admin/ProductFilterBar.tsx:34
|
||
|
||
src/components/admin/ProductSyncBanner.tsx:46
|
||
|
||
src/components/admin/ProductTableBody.tsx:81
|
||
|
||
src/components/admin/ProductTableBody.tsx:101
|
||
|
||
src/components/admin/ProductTableBody.tsx:175
|
||
|
||
src/components/admin/ProductTableBody.tsx:194
|
||
|
||
src/components/admin/ProductTableBody.tsx:220
|
||
|
||
src/components/admin/ProductTableBody.tsx:226
|
||
|
||
src/components/admin/ProductTableClient.tsx:64
|
||
|
||
src/components/admin/ProductTableClient.tsx:84
|
||
|
||
src/components/admin/ProductTableClient.tsx:220
|
||
|
||
src/components/admin/ProductTableClient.tsx:239
|
||
|
||
src/components/admin/ProductTableClient.tsx:264
|
||
|
||
src/components/admin/ProductTableClient.tsx:270
|
||
|
||
src/components/admin/ProductsClient.tsx:471
|
||
|
||
src/components/admin/ProductsClient.tsx:512
|
||
|
||
src/components/admin/ProductsClient.tsx:553
|
||
|
||
src/components/admin/ProductsClient.tsx:641
|
||
|
||
src/components/admin/ProductsClient.tsx:684
|
||
|
||
src/components/admin/ProductsClient.tsx:706
|
||
|
||
src/components/admin/ProductsClient.tsx:712
|
||
|
||
src/components/admin/ReportsDashboard.tsx:672
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:146
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:291
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:311
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:317
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:356
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:373
|
||
|
||
src/components/admin/SettingsClient.tsx:77
|
||
|
||
src/components/admin/SettingsClient.tsx:176
|
||
|
||
src/components/admin/SettingsSections.tsx:49
|
||
|
||
src/components/admin/SettingsSections.tsx:404
|
||
|
||
src/components/admin/SettingsSections.tsx:410
|
||
|
||
src/components/admin/SettingsSections.tsx:427
|
||
|
||
src/components/admin/SettingsSections.tsx:433
|
||
|
||
src/components/admin/SettingsSections.tsx:500
|
||
|
||
src/components/admin/SettingsSections.tsx:531-533
|
||
|
||
src/components/admin/SettingsSections.tsx:557
|
||
|
||
src/components/admin/SettingsSections.tsx:588-589
|
||
|
||
src/components/admin/SettingsSections.tsx:607
|
||
|
||
src/components/admin/SettingsSections.tsx:653
|
||
|
||
src/components/admin/SettingsSections.tsx:659
|
||
|
||
src/components/admin/SettingsSections.tsx:663
|
||
|
||
src/components/admin/SettingsSections.tsx:679
|
||
|
||
src/components/admin/SettingsSections.tsx:721
|
||
|
||
src/components/admin/SettingsSections.tsx:725
|
||
|
||
src/components/admin/ShippingFulfillmentPanel.tsx:178
|
||
|
||
src/components/admin/ShippingFulfillmentPanel.tsx:197
|
||
|
||
src/components/admin/SquareSyncWidget.tsx:169
|
||
|
||
src/components/admin/SquareSyncWidget.tsx:176
|
||
|
||
src/components/admin/SquareSyncWidget.tsx:183
|
||
|
||
src/components/admin/StopMessagingForm.tsx:97
|
||
|
||
src/components/admin/StopMessagingForm.tsx:129
|
||
|
||
src/components/admin/StopMessagingForm.tsx:151
|
||
|
||
src/components/admin/StopTableClient.tsx:378
|
||
|
||
src/components/admin/StopTableClient.tsx:400
|
||
|
||
src/components/admin/StopTableClient.tsx:845
|
||
|
||
src/components/admin/StopTableClient.tsx:871
|
||
|
||
src/components/admin/StopTableClient.tsx:896
|
||
|
||
src/components/admin/StopTableClient.tsx:1032
|
||
|
||
src/components/admin/StopTableClient.tsx:1055
|
||
|
||
src/components/admin/StopTableClient.tsx:1077
|
||
|
||
src/components/admin/StopTableClient.tsx:1083
|
||
|
||
src/components/admin/TemplateEditForm.tsx:151
|
||
|
||
src/components/admin/TemplateEditForm.tsx:199
|
||
|
||
src/components/admin/TemplateEditForm.tsx:205
|
||
|
||
src/components/admin/TemplateEditForm.tsx:246
|
||
|
||
src/components/admin/TemplateEditForm.tsx:612
|
||
|
||
src/components/admin/TemplateEditForm.tsx:622
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:567
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:619
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:341
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:349
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:357
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:365
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:581
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:591
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:601
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:626
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:645
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:670
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:736
|
||
|
||
src/components/admin/ToastContainer.tsx:79
|
||
|
||
src/components/admin/ToastContainer.tsx:138
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:166
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:184
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:194
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:282
|
||
|
||
src/components/admin/UsersPage.tsx:345
|
||
|
||
src/components/admin/UsersPage.tsx:358
|
||
|
||
src/components/admin/UsersPage.tsx:370
|
||
|
||
src/components/admin/UsersPage.tsx:416
|
||
|
||
src/components/admin/UsersPage.tsx:423
|
||
|
||
src/components/admin/UsersPage.tsx:437
|
||
|
||
src/components/admin/UsersPage.tsx:443
|
||
|
||
src/components/admin/UsersPage.tsx:449
|
||
|
||
src/components/admin/UsersPage.tsx:456
|
||
|
||
src/components/admin/UsersPage.tsx:492
|
||
|
||
src/components/admin/UsersPage.tsx:498
|
||
|
||
src/components/admin/UsersPage.tsx:520
|
||
|
||
src/components/admin/UsersPage.tsx:646
|
||
|
||
src/components/admin/UsersPage.tsx:678
|
||
|
||
src/components/admin/UsersPage.tsx:684
|
||
|
||
src/components/admin/UsersPage.tsx:709
|
||
|
||
src/components/admin/UsersPage.tsx:716-719
|
||
|
||
src/components/admin/UsersPage.tsx:724
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:574
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:581
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:588
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:708
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:715
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:812
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:890
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:1046
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:84
|
||
|
||
src/components/admin/WebhookLogsSection.tsx:69
|
||
|
||
src/components/admin/WebhookLogsSection.tsx:113
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:80
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:86
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:94
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:99
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:157
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:40
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:54
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:102
|
||
|
||
src/components/admin/design-system/AdminButton.tsx:89
|
||
|
||
src/components/admin/design-system/AdminButton.tsx:129
|
||
|
||
src/components/admin/design-system/AdminDeleteConfirm.tsx:53
|
||
|
||
src/components/admin/design-system/AdminDeleteConfirm.tsx:59
|
||
|
||
src/components/admin/design-system/AdminFilterBar.tsx:65
|
||
|
||
src/components/admin/design-system/AdminFilterBar.tsx:90
|
||
|
||
src/components/admin/design-system/AdminFilterBar.tsx:102
|
||
|
||
src/components/admin/design-system/AdminFilterBar.tsx:122
|
||
|
||
src/components/admin/design-system/AdminModal.tsx:52
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:20
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:53
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:68
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:101
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:110
|
||
|
||
src/components/admin/shared/DataTable.tsx:100
|
||
|
||
src/components/admin/shared/DataTable.tsx:109
|
||
|
||
src/components/admin/shared/FilterBar.tsx:86
|
||
|
||
src/components/admin/stops/StopsCalendar.tsx:201
|
||
|
||
src/components/admin/stops/StopsCalendar.tsx:208
|
||
|
||
src/components/admin/stops/StopsCalendar.tsx:215
|
||
|
||
src/components/changelog/ChangelogFeed.tsx:102
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:113
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:111
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:129
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:143
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:149
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:173
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:179
|
||
|
||
src/components/legal/CookieConsentBanner.tsx:185
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx:127
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx:149
|
||
|
||
src/components/notifications/ToastNotification.tsx:110
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:156
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:222
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:229
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:238
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:245
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:252
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:301-304
|
||
|
||
src/components/providers/ErrorBoundary.tsx:45
|
||
|
||
src/components/pwa/InstallPrompt.tsx:84
|
||
|
||
src/components/pwa/InstallPrompt.tsx:90
|
||
|
||
src/components/referral/ReferralSystem.tsx:91
|
||
|
||
src/components/referral/ReferralSystem.tsx:148
|
||
|
||
src/components/referral/ReferralSystem.tsx:157
|
||
|
||
src/components/referral/ReferralSystem.tsx:166
|
||
|
||
src/components/referral/ReferralSystem.tsx:176
|
||
|
||
src/components/route-trace/AdminLookupPage.tsx:71
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:224
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:281
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:318
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:572
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:578
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:121
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:322
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:333
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:346
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:354
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:418
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:528
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:602
|
||
|
||
src/components/route-trace/LotListTable.tsx:185
|
||
|
||
src/components/route-trace/LotListTable.tsx:198
|
||
|
||
src/components/route-trace/LotListTable.tsx:223
|
||
|
||
src/components/route-trace/LotListTable.tsx:243
|
||
|
||
src/components/route-trace/LotListTable.tsx:250
|
||
|
||
src/components/route-trace/LotListTable.tsx:257
|
||
|
||
src/components/route-trace/LotListTable.tsx:264
|
||
|
||
src/components/route-trace/LotListTable.tsx:271
|
||
|
||
src/components/route-trace/LotListTable.tsx:278
|
||
|
||
src/components/route-trace/QRScanModal.tsx:200
|
||
|
||
src/components/route-trace/QRScanModal.tsx:212
|
||
|
||
src/components/route-trace/RouteTraceDashboard.tsx:596
|
||
|
||
src/components/route-trace/RouteTraceDashboard.tsx:602
|
||
|
||
src/components/route-trace/RouteTracePage.tsx:113
|
||
|
||
src/components/route-trace/ShareTraceButton.tsx:26
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:93
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:110
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:133
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:155
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:287
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:293
|
||
|
||
src/components/shared/ThemeToggle.tsx:20
|
||
|
||
src/components/storefront/CartToast.tsx:31
|
||
|
||
src/components/storefront/CartToast.tsx:46
|
||
|
||
src/components/storefront/HeroSection.tsx:66
|
||
|
||
src/components/storefront/HeroSection.tsx:74
|
||
|
||
src/components/storefront/HeroSection.tsx:119
|
||
|
||
src/components/storefront/HeroSection.tsx:127
|
||
|
||
src/components/storefront/HeroSection.tsx:159
|
||
|
||
src/components/storefront/HeroSection.tsx:167
|
||
|
||
src/components/storefront/IndianRiverPaginatedStops.tsx:94
|
||
|
||
src/components/storefront/IndianRiverPaginatedStops.tsx:158
|
||
|
||
src/components/storefront/IndianRiverPaginatedStops.tsx:165
|
||
|
||
src/components/storefront/PaginatedStops.tsx:95
|
||
|
||
src/components/storefront/PaginatedStops.tsx:159
|
||
|
||
src/components/storefront/PaginatedStops.tsx:166
|
||
|
||
src/components/storefront/ProductCard.tsx:99
|
||
|
||
src/components/storefront/ProductCard.tsx:112
|
||
|
||
src/components/storefront/ProductCard.tsx:126
|
||
|
||
src/components/storefront/QuickCartSheet.tsx:228
|
||
|
||
src/components/storefront/QuickCartSheet.tsx:369
|
||
|
||
src/components/storefront/StorefrontHeader.tsx:139
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:220
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:330
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:340
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:586
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:592
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:614
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:620
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:707
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:336
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:391
|
||
|
||
src/components/storefront/ZipCodeSearch.tsx:60
|
||
|
||
src/components/storefront/ZipCodeSearch.tsx:86
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:392
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:614
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:620
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:667
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:675
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:801
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:809
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:873
|
||
|
||
src/components/water/WaterAdminClient.tsx:247
|
||
|
||
src/components/water/WaterAdminClient.tsx:417
|
||
|
||
src/components/water/WaterAdminClient.tsx:484
|
||
|
||
src/components/water/WaterAdminClient.tsx:551
|
||
|
||
src/components/water/WaterAdminClient.tsx:571
|
||
|
||
src/components/water/WaterAdminClient.tsx:585
|
||
|
||
src/components/water/WaterAdminClient.tsx:653
|
||
|
||
src/components/water/WaterAdminClient.tsx:710
|
||
|
||
src/components/water/WaterFieldClient.tsx:380
|
||
|
||
src/components/water/WaterFieldClient.tsx:386
|
||
|
||
src/components/water/WaterFieldClient.tsx:403
|
||
|
||
src/components/water/WaterFieldClient.tsx:417
|
||
|
||
src/components/water/WaterFieldClient.tsx:423
|
||
|
||
src/components/water/WaterFieldClient.tsx:440
|
||
|
||
src/components/water/WaterFieldClient.tsx:505
|
||
|
||
src/components/wholesale/DepositModal.tsx:84
|
||
|
||
src/components/wholesale/DepositModal.tsx:91
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:40
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:135
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:144
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:159
|
||
|
||
src/components/wholesale/admin/CustomerPricingPanel.tsx:55
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:425
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:433
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:445
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:452
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:469
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:258
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:374
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:387
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:395
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:413
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:431
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:441
|
||
|
||
src/components/wholesale/admin/PriceSheetModal.tsx:40
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:224
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:236
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:244
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:125
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:138
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:163
|
||
|
||
src/components/wholesale/admin/SettingsTab.tsx:254
|
||
|
||
src/components/wholesale/admin/WebhookSettingsSection.tsx:108
|
||
|
||
⚠ Performance: State only used in handlers ×48
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/rerender-state-only-in-handlers
|
||
Each update to "activeBrandName" redraws your component for
|
||
nothing because this useState is set but never shown on
|
||
screen.
|
||
→ Use useRef instead of useState when the value is only set
|
||
and never shown on screen. `ref.current = ...` updates it
|
||
without redrawing the component.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:32
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:472-473
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:23
|
||
|
||
src/app/tuxedo/contact/ContactClientPage.tsx:22
|
||
|
||
src/app/tuxedo/page.tsx:435
|
||
|
||
src/app/wholesale/portal/page.tsx:239
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:55
|
||
|
||
src/components/admin/CampaignListPanel.tsx:340
|
||
|
||
src/components/admin/ContactImportForm.tsx:92-95
|
||
|
||
src/components/admin/ContactImportForm.tsx:101
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:320
|
||
|
||
src/components/admin/HarvestReach/MatchingCustomersPanel.tsx:50
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:224-225
|
||
|
||
src/components/admin/NewProductForm.tsx:25
|
||
|
||
src/components/admin/OrderEditForm.tsx:62
|
||
|
||
src/components/admin/ProductEditForm.tsx:45
|
||
|
||
src/components/admin/ProductFormModal.tsx:109
|
||
|
||
src/components/admin/SettingsSections.tsx:88-89
|
||
|
||
src/components/admin/SettingsSections.tsx:97-98
|
||
|
||
src/components/admin/SettingsSections.tsx:108-111
|
||
|
||
src/components/admin/SquareSyncWidget.tsx:24
|
||
|
||
src/components/admin/StopEditForm.tsx:39
|
||
|
||
src/components/admin/StopMessagingForm.tsx:29
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:170
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:86
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:94
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:104-107
|
||
|
||
src/components/admin/UsersPage.tsx:126
|
||
|
||
src/components/admin/orders/OrdersFilterButton.tsx:20
|
||
|
||
src/components/landing/FeaturesAndStats.tsx:173
|
||
|
||
src/components/landing/HeroSection.tsx:20
|
||
|
||
src/components/route-trace/QRScanModal.tsx:64
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:177
|
||
|
||
src/components/water/WaterAdminClient.tsx:272
|
||
|
||
src/components/water/WaterFieldClient.tsx:148
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:46
|
||
|
||
⚠ Performance: RegExp built inside a loop
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/js-hoist-regexp
|
||
`new RegExp()` rebuilds the pattern on every loop pass.
|
||
Move it to a constant outside the loop.
|
||
→ Move `new RegExp(...)` (or large regex literals) to a
|
||
constant outside the loop so it isn't rebuilt on every pass
|
||
|
||
src/lib/excel-parser.ts:74
|
||
|
||
⚠ Bugs: Event logic handled in an effect ×35
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-event-handler
|
||
Faking an event handler with state plus a useEffect costs
|
||
an extra render & runs late.
|
||
→ Run the side effect in the event handler that triggers
|
||
it, instead of watching its state from a useEffect. See
|
||
https://react.dev/learn/you-might-not-need-an-effect#sharing-logic-between-event-handlers
|
||
|
||
src/app/cart/CartClient.tsx:47
|
||
|
||
src/app/checkout/CheckoutClient.tsx:45
|
||
|
||
src/components/admin/AIProviderPanel.tsx:113
|
||
|
||
src/components/admin/AddStopModal.tsx:50
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:209
|
||
|
||
src/components/admin/CommandPalette.tsx:216
|
||
|
||
src/components/admin/EditLocationModal.tsx:46
|
||
|
||
src/components/admin/EditStopModal.tsx:56
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:73
|
||
|
||
src/components/admin/ProductsClient.tsx:397
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:65
|
||
|
||
src/components/admin/SquareSyncWidget.tsx:35
|
||
|
||
src/components/admin/TaxDashboard.tsx:139
|
||
|
||
src/components/admin/TaxDashboard.tsx:196
|
||
|
||
src/components/admin/TaxDashboard.tsx:205
|
||
|
||
src/components/admin/orders/OrdersFilterButton.tsx:25
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx:48
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:181
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:38
|
||
|
||
src/components/storefront/BrandStylesProvider.tsx:19-22
|
||
|
||
src/components/water/WaterFieldClient.tsx:162
|
||
|
||
⚠ Bugs: State updates chained through effects ×10
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-chain-state-updates
|
||
Chaining state updates triggers an extra render each step.
|
||
→ Set all the related state together in the event handler
|
||
that starts it, instead of having one useEffect react to a
|
||
state change and set more state. See
|
||
https://react.dev/learn/you-might-not-need-an-effect#chains-of-computations
|
||
|
||
src/app/cart/CartClient.tsx:49
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:61
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:80
|
||
|
||
src/components/admin/CommandPalette.tsx:220
|
||
|
||
src/components/admin/CommandPalette.tsx:228
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:81-83
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:201
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:50
|
||
|
||
⚠ Performance: Empty default prop breaks memo ×16
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/rerender-memo-with-default-value
|
||
This keeps redrawing children that compare props because
|
||
default prop value [] makes a brand new array every render,
|
||
so move it to a constant at the top of the file
|
||
→ Move it to the top of the file: `const EMPTY_ITEMS:
|
||
Item[] = []`, then use that as the default value
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:30
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:100
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:28
|
||
|
||
src/components/admin/CommunicationsPage.tsx:96-99
|
||
|
||
src/components/admin/NewProductForm.tsx:17
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:34
|
||
|
||
src/components/admin/ProductFormModal.tsx:88
|
||
|
||
src/components/admin/ProductsClient.tsx:43
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:37
|
||
|
||
src/components/admin/shared/FilterBar.tsx:34-35
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:217
|
||
|
||
src/components/storefront/ZipCodeSearch.tsx:20
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:31
|
||
|
||
⚠ Accessibility: Click handler missing keyboard handler ×46
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/click-events-have-key-events
|
||
Keyboard users can't trigger this click handler because
|
||
there's no keyboard one, so add `onKeyUp`, `onKeyDown`, or
|
||
`onKeyPress`.
|
||
→ Pair `onClick` with a key handler so keyboard users can
|
||
trigger it.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:178
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:612
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:365
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:498
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:194
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:448
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:257
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:283
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:882
|
||
|
||
src/components/admin/CampaignListPanel.tsx:114
|
||
|
||
src/components/admin/CommandPalette.tsx:261
|
||
|
||
src/components/admin/ElegantModal.tsx:36
|
||
|
||
src/components/admin/GlassModal.tsx:48
|
||
|
||
src/components/admin/HarvestReach/SegmentEditModal.tsx:44
|
||
|
||
src/components/admin/HarvestReach/SegmentListSidebar.tsx:91
|
||
|
||
src/components/admin/MoreSheet.tsx:79
|
||
|
||
src/components/admin/NewProductForm.tsx:243
|
||
|
||
src/components/admin/ProductEditForm.tsx:256
|
||
|
||
src/components/admin/ProductFormModal.tsx:244
|
||
|
||
src/components/admin/ProductFormModal.tsx:322
|
||
|
||
src/components/admin/ProductTableBody.tsx:189
|
||
|
||
src/components/admin/ProductTableBody.tsx:206
|
||
|
||
src/components/admin/ProductTableClient.tsx:234
|
||
|
||
src/components/admin/ProductTableClient.tsx:251
|
||
|
||
src/components/admin/ProductsClient.tsx:536
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:165
|
||
|
||
src/components/admin/StopTableClient.tsx:861
|
||
|
||
src/components/admin/StopTableClient.tsx:915
|
||
|
||
src/components/admin/TemplateEditForm.tsx:133
|
||
|
||
src/components/admin/UpgradePlanModal.tsx:149
|
||
|
||
src/components/admin/UsersPage.tsx:432
|
||
|
||
src/components/admin/UsersPage.tsx:511
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:51
|
||
|
||
src/components/admin/design-system/AdminModal.tsx:28
|
||
|
||
src/components/admin/orders/OrdersFilterButton.tsx:70
|
||
|
||
src/components/cart/CartRestoredToast.tsx:25
|
||
|
||
src/components/changelog/ChangelogFeed.tsx:79
|
||
|
||
src/components/landing/HeroSection.tsx:564
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx:174
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:288
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:232
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:93
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:86
|
||
|
||
src/components/wholesale/DepositModal.tsx:43
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:32
|
||
|
||
src/components/wholesale/admin/PriceSheetModal.tsx:31
|
||
|
||
⚠ Bugs: State initialized from a mount effect ×23
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-initialize-state
|
||
Your users see an extra render with empty "mounted" because
|
||
a useEffect sets its starting value.
|
||
→ Pass the initial value directly to useState() instead of
|
||
setting it from a mount-only useEffect. For SSR hydration,
|
||
prefer useSyncExternalStore().
|
||
|
||
src/components/admin/OfflineBanner.tsx:12-13
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:80
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:85
|
||
|
||
src/components/admin/PullToRefresh.tsx:38
|
||
|
||
src/components/admin/SettingsClient.tsx:145
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:81
|
||
|
||
src/components/notifications/ToastNotification.tsx:152
|
||
|
||
src/components/pwa/InstallPrompt.tsx:18
|
||
|
||
src/components/pwa/InstallPrompt.tsx:23
|
||
|
||
src/components/shared/ThemeToggle.tsx:11
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:68
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:195
|
||
|
||
src/components/ui/ScrollAnimations.tsx:40
|
||
|
||
src/components/water/WaterAdminClient.tsx:327
|
||
|
||
src/context/CartContext.tsx:107-108
|
||
|
||
src/context/CartContext.tsx:117-121
|
||
|
||
src/context/CartContext.tsx:129-131
|
||
|
||
src/context/CartContext.tsx:135
|
||
|
||
⚠ Performance: New function passed as a prop
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/jsx-no-new-function-as-prop
|
||
This child redraws every render because the prop gets a
|
||
brand new function each time.
|
||
→ Wrap the callback in `useCallback` or move it outside the
|
||
component so memoized children do not redraw every render.
|
||
|
||
src/components/admin/ProductTableClient.tsx:116
|
||
|
||
✖ Bugs: Component defined inside another component
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-nested-component-definition
|
||
Your users lose all state in "SortIcon" on every render
|
||
because it's defined inside "StopTableClient", so move it
|
||
out to the top of the file.
|
||
→ Move it to module scope or a separate file so React does
|
||
not recreate the component and erase its state on every
|
||
parent render.
|
||
|
||
src/components/admin/StopTableClient.tsx:259
|
||
┌──────────────────────────────────────────────────────────────┐
|
||
│ 258 | // Sort icon component │
|
||
│ > 259 | const SortIcon = ({ field }: { field: SortField }[0m… │
|
||
│ | ^ │
|
||
│ 260 | <span className={`inline-flex ml-1.5 ${sortFiel[0m… │
|
||
└──────────────────────────────────────────────────────────────┘
|
||
|
||
⚠ Performance: Import from a barrel file ×20
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-barrel-import
|
||
Importing from an index file pulls in extra code. Import
|
||
directly from the source file instead.
|
||
→ Import from the direct path: `import { Button } from
|
||
'./components/Button'` instead of `./components`
|
||
|
||
db/client.ts:27
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:19
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:14
|
||
|
||
src/components/admin/ContactListPanel.tsx:7
|
||
|
||
src/components/admin/HeadgateEditForm.tsx:6
|
||
|
||
src/components/admin/MessageLogPanel.tsx:7
|
||
|
||
src/components/admin/NewProductForm.tsx:9
|
||
|
||
src/components/admin/NewStopForm.tsx:7
|
||
|
||
src/components/admin/OrderEditForm.tsx:6
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:8
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:8
|
||
|
||
src/components/admin/ProductEditForm.tsx:9
|
||
|
||
src/components/admin/SettingsSections.tsx:24
|
||
|
||
src/components/admin/ShippingFulfillmentPanel.tsx:9
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:11
|
||
|
||
src/components/admin/StopEditForm.tsx:6
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:25
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:51
|
||
|
||
src/components/admin/WaterLogEntryEditForm.tsx:6
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:6
|
||
|
||
⚠ Performance: State initializer runs on every render ×5
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/rerender-lazy-state-init
|
||
useState(buildFaqCategories()) re-runs buildFaqCategories()
|
||
on every render & throws the result away.
|
||
→ Wrap expensive initial state in an arrow function so the
|
||
initializer does not rerun and get thrown away on every
|
||
render.
|
||
|
||
src/app/indian-river-direct/faq/FAQClientPage.tsx:135
|
||
|
||
src/components/admin/OrderEditForm.tsx:74
|
||
|
||
src/components/admin/UsersPage.tsx:120
|
||
|
||
src/components/admin/stops/StopsCalendar.tsx:82
|
||
|
||
src/components/landing/FeaturesAndStats.tsx:174
|
||
|
||
⚠ Performance: useEffect setState flashes on mount
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/rendering-hydration-no-flicker
|
||
This flashes for your users because useEffect(setState, [])
|
||
runs after the first paint, so use useSyncExternalStore, or
|
||
add suppressHydrationWarning
|
||
→ Use `useSyncExternalStore(subscribe, getSnapshot,
|
||
getServerSnapshot)` or add `suppressHydrationWarning` to
|
||
the element
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:194
|
||
|
||
⚠ Maintainability: deslop/unused-export ×126
|
||
Unused export: `tenantStatusEnum` is exported but no module
|
||
imports it, so it expands the public surface and can
|
||
mislead callers about supported API.
|
||
→ Drop the `export` keyword (or remove the declaration) if
|
||
no other module uses this symbol.
|
||
|
||
db/schema/enums.ts:11
|
||
|
||
db/schema/enums.ts:20-29
|
||
|
||
db/schema/enums.ts:39
|
||
|
||
db/schema/enums.ts:48-54
|
||
|
||
db/schema/enums.ts:62-65
|
||
|
||
src/actions/admin/password.ts:16
|
||
|
||
src/actions/billing/stripe-checkout.ts:30
|
||
|
||
src/actions/communications/contacts.ts:197
|
||
|
||
src/actions/communications/contacts.ts:383
|
||
|
||
src/actions/communications/import-contacts.ts:170
|
||
|
||
src/actions/communications/segments.ts:109
|
||
|
||
src/actions/communications/segments.ts:163
|
||
|
||
src/actions/dashboard.ts:229
|
||
|
||
src/actions/email-automation/abandoned-cart.ts:246
|
||
|
||
src/actions/harvest-reach/campaigns.ts:77
|
||
|
||
src/actions/integrations/ai-providers.ts:195
|
||
|
||
src/actions/integrations/ai-providers.ts:207
|
||
|
||
src/actions/integrations/ai-providers.ts:227
|
||
|
||
src/actions/offline-dispatcher.ts:48
|
||
|
||
src/actions/orders.ts:137
|
||
|
||
src/actions/orders.ts:143
|
||
|
||
src/actions/orders.ts:149
|
||
|
||
src/actions/time-tracking/index.ts:159
|
||
|
||
src/actions/time-tracking/index.ts:172
|
||
|
||
src/actions/water-log/admin.ts:127
|
||
|
||
src/actions/water-log/admin.ts:1010-1011
|
||
|
||
src/actions/water-log/field.ts:281
|
||
|
||
src/actions/water-log/field.ts:315
|
||
|
||
src/actions/water-log/field.ts:375
|
||
|
||
src/actions/wholesale-auth.ts:37
|
||
|
||
src/actions/wholesale-register.ts:261
|
||
|
||
src/auth.config.ts:66
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:827
|
||
|
||
src/components/admin/EditStopModal.tsx:437
|
||
|
||
src/components/admin/Toast.tsx:76
|
||
|
||
src/components/admin/ToastContainer.tsx:122
|
||
|
||
src/components/admin/command-palette-data.ts:389
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:85
|
||
|
||
src/components/admin/design-system/AdminBadge.tsx:159
|
||
|
||
src/components/admin/design-system/AdminBadge.tsx:177
|
||
|
||
src/components/admin/design-system/AdminCard.tsx:31
|
||
|
||
src/components/admin/design-system/AdminCard.tsx:44
|
||
|
||
src/components/admin/design-system/AdminDeleteConfirm.tsx:73
|
||
|
||
src/components/admin/design-system/AdminFilterTabs.tsx:141
|
||
|
||
src/components/admin/design-system/AdminFormElements.tsx:164
|
||
|
||
src/components/admin/design-system/AdminFormElements.tsx:191
|
||
|
||
src/components/admin/design-system/AdminFormElements.tsx:210
|
||
|
||
src/components/admin/design-system/AdminPagination.tsx:89
|
||
|
||
src/components/admin/design-system/AdminTable.tsx:76
|
||
|
||
src/components/admin/design-system/AdminToggle.tsx:70
|
||
|
||
src/components/admin/design-system/Skeleton.tsx:35
|
||
|
||
src/components/admin/design-system/Skeleton.tsx:50
|
||
|
||
src/components/admin/design-system/Skeleton.tsx:67
|
||
|
||
src/components/admin/design-system/Skeleton.tsx:81
|
||
|
||
src/components/admin/design-system/Skeleton.tsx:149
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:12
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:215
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:420
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:439
|
||
|
||
src/components/transitions/LoadingFade.tsx:39
|
||
|
||
src/components/ui/ScrollAnimations.tsx:28
|
||
|
||
src/components/ui/ScrollAnimations.tsx:249
|
||
|
||
src/lib/ai-provider-models.ts:5
|
||
|
||
src/lib/ai-provider-models.ts:40
|
||
|
||
src/lib/analytics.ts:8
|
||
|
||
src/lib/analytics.ts:121
|
||
|
||
src/lib/analytics.ts:127
|
||
|
||
src/lib/brand-scope.ts:22
|
||
|
||
src/lib/column-detector.ts:155
|
||
|
||
src/lib/column-detector.ts:214
|
||
|
||
src/lib/feature-flags.ts:117
|
||
|
||
src/lib/format-date.ts:31
|
||
|
||
src/lib/pricing.ts:134
|
||
|
||
src/lib/pricing.ts:171
|
||
|
||
src/lib/pricing.ts:176
|
||
|
||
src/lib/pricing.ts:181
|
||
|
||
src/lib/pricing.ts:185
|
||
|
||
src/lib/pricing.ts:189
|
||
|
||
src/lib/pricing.ts:193
|
||
|
||
src/lib/pricing.ts:197
|
||
|
||
src/lib/pricing.ts:201-202
|
||
|
||
src/lib/pwa.ts:34
|
||
|
||
src/lib/pwa.ts:40
|
||
|
||
src/lib/pwa.ts:49
|
||
|
||
src/lib/rate-limit.ts:79
|
||
|
||
src/lib/rate-limit.ts:89-91
|
||
|
||
src/lib/sentry.ts:65
|
||
|
||
src/lib/sentry.ts:73
|
||
|
||
src/lib/storage.ts:25
|
||
|
||
src/lib/storage.ts:51
|
||
|
||
src/lib/storage.ts:84
|
||
|
||
src/lib/storage.ts:101
|
||
|
||
src/lib/storage.ts:121
|
||
|
||
src/lib/stripe-billing.ts:36
|
||
|
||
src/lib/stripe-billing.ts:102
|
||
|
||
src/lib/stripe-billing.ts:171
|
||
|
||
src/lib/stripe-billing.ts:215
|
||
|
||
src/lib/stripe-billing.ts:259
|
||
|
||
src/lib/stripe-billing.ts:277
|
||
|
||
src/lib/stripe-billing.ts:287
|
||
|
||
src/lib/stripe-billing.ts:293
|
||
|
||
src/lib/stripe-billing.ts:317
|
||
|
||
src/lib/stripe-billing.ts:340
|
||
|
||
src/lib/stripe-billing.ts:344
|
||
|
||
src/lib/stripe-billing.ts:352
|
||
|
||
src/lib/stripe-billing.ts:359
|
||
|
||
src/lib/stripe-billing.ts:365
|
||
|
||
src/lib/stripe-billing.ts:377
|
||
|
||
src/lib/stripe-billing.ts:384
|
||
|
||
src/lib/stripe-billing.ts:388
|
||
|
||
src/lib/stripe-billing.ts:399
|
||
|
||
src/lib/stripe-billing.ts:416
|
||
|
||
src/lib/stripe-billing.ts:616
|
||
|
||
src/lib/stripe-billing.ts:643
|
||
|
||
src/lib/stripe-billing.ts:656
|
||
|
||
src/lib/stripe-billing.ts:660
|
||
|
||
src/lib/water-log-reporting.ts:38
|
||
|
||
⚠ Maintainability: Static value rebuilt every render ×35
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/prefer-module-scope-static-value
|
||
`analysisLabels` inside `ImportCenterClient` uses no local
|
||
state but is rebuilt every render, so it looks new each
|
||
time & breaks memoized children. Move it to the top of the
|
||
file, outside the component.
|
||
→ Move the value above the component, at the top of the
|
||
file. It doesn't use local state, so rebuilding it each
|
||
update is wasted and makes it look new every time.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:136
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:659
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1195
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:280
|
||
|
||
src/app/admin/v2/stops/page.tsx:246
|
||
|
||
src/app/api/reports/export/route.ts:77
|
||
|
||
src/app/api/time-tracking/export/route.ts:127
|
||
|
||
src/app/api/time-tracking/export/route.ts:169
|
||
|
||
src/app/api/time-tracking/export/route.ts:190
|
||
|
||
src/app/api/time-tracking/export/route.ts:231
|
||
|
||
src/app/api/water-logs/export/route.ts:46
|
||
|
||
src/app/brands/page.tsx:59
|
||
|
||
src/app/trace/[lotNumber]/page.tsx:80
|
||
|
||
src/app/wholesale/employee/page.tsx:17
|
||
|
||
src/components/admin/AddLocationModal.tsx:85
|
||
|
||
src/components/admin/CreateUserModal.tsx:162
|
||
|
||
src/components/admin/DashboardClient.tsx:159
|
||
|
||
src/components/admin/EditLocationModal.tsx:105
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:306
|
||
|
||
src/components/admin/UsersPage.tsx:42
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:999
|
||
|
||
src/components/admin/design-system/AdminActionMenu.tsx:95
|
||
|
||
src/components/admin/design-system/AdminFilterBar.tsx:36
|
||
|
||
src/components/admin/design-system/AdminFormElements.tsx:192
|
||
|
||
src/components/admin/design-system/AdminTable.tsx:77
|
||
|
||
src/components/admin/design-system/Skeleton.tsx:15
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:15
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:216
|
||
|
||
src/components/notifications/ToastNotification.tsx:50
|
||
|
||
src/components/notifications/ToastNotification.tsx:73
|
||
|
||
src/components/notifications/ToastNotification.tsx:80
|
||
|
||
src/components/onboarding/OnboardingFlow.tsx:276
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:147
|
||
|
||
src/components/storefront/ProductCard.tsx:39
|
||
|
||
src/components/wholesale/OrderDetailsModal.tsx:14
|
||
|
||
⚠ Accessibility: Custom modal instead of dialog ×6
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/prefer-html-dialog
|
||
Keyboard users can tab out of this `role="dialog"` modal
|
||
because it has no built-in focus trapping, so use the
|
||
native `<dialog>`, which gives you focus trapping, `Escape`
|
||
to close, and the backdrop for free.
|
||
→ Replace the wrapper with `<dialog>` and open it with
|
||
`dialog.showModal()`. For the trigger, prefer `<button
|
||
commandfor="id" command="show-modal">` (Chrome 135+), or a
|
||
`useRef` with `dialogRef.current?.showModal()`.
|
||
|
||
src/app/cart/CartClient.tsx:206
|
||
|
||
src/components/admin/CommandPalette.tsx:262
|
||
|
||
src/components/admin/ProductFormModal.tsx:256
|
||
|
||
src/components/admin/ProductsClient.tsx:541
|
||
|
||
src/components/admin/StopsCalendarClient.tsx:613
|
||
|
||
src/components/admin/products/StockAdjustButton.tsx:79
|
||
|
||
⚠ Performance: transition: all animates everything ×4
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-transition-all
|
||
This can stutter because transition: "all" animates every
|
||
property, even slow layout ones, so list only the
|
||
properties you actually change
|
||
→ List the specific properties: `transition: "opacity
|
||
200ms, transform 200ms"`. In Tailwind, use
|
||
`transition-colors`, `transition-opacity`, or
|
||
`transition-transform`
|
||
|
||
src/components/landing/HeroSection.tsx:344
|
||
|
||
src/components/landing/HeroSection.tsx:367
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:483
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:539
|
||
|
||
⚠ Performance: Intl formatter rebuilt each call ×6
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/js-hoist-intl
|
||
This is slow because new Intl.NumberFormat() rebuilds on
|
||
every call inside a function, so move it to the top of the
|
||
file, or wrap it in useMemo
|
||
→ Move `new Intl.NumberFormat(...)` to the top of the file
|
||
or wrap it in `useMemo`. Building one is slow, so don't
|
||
redo it on every call
|
||
|
||
src/app/admin/orders/[id]/page.tsx:29
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:86
|
||
|
||
src/components/admin/DashboardClient.tsx:95
|
||
|
||
src/components/admin/OrderEditForm.tsx:54
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:34
|
||
|
||
src/components/admin/ShippingFulfillmentPanel.tsx:77
|
||
|
||
⚠ Bugs: Data passed to parent via effect
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-pass-data-to-parent
|
||
Handing data back to a parent from a useEffect costs your
|
||
users an extra render.
|
||
→ Fetch the data in the parent and pass it down as a prop
|
||
(or return it from the hook), instead of handing it back up
|
||
through a prop callback in a useEffect. See
|
||
https://react.dev/learn/you-might-not-need-an-effect#passing-data-to-the-parent
|
||
|
||
src/components/admin/ProductFormModal.tsx:148
|
||
|
||
⚠ Performance: Loading useState forces extra render ×4
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/rendering-usetransition-loading
|
||
This adds an extra render because useState for "isLoading"
|
||
re-renders just for the loading flag, so if it's a state
|
||
change & not a data fetch, use useTransition instead
|
||
→ Replace with `const [isPending, startTransition] =
|
||
useTransition()`, which skips the extra render for the
|
||
loading flag
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:215
|
||
|
||
src/components/admin/LocationsTab.tsx:53
|
||
|
||
src/components/admin/StopTableClient.tsx:97
|
||
|
||
src/components/route-trace/QRScanModal.tsx:62
|
||
|
||
⚠ Maintainability: Format method on z.string() ×30
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/zod-v4-prefer-top-level-string-formats
|
||
This `z.string().<format>()` check is deprecated in Zod 4,
|
||
so it can break during the upgrade.
|
||
→ Use the Zod 4 top-level format checks like `z.email()`,
|
||
`z.uuid()`, or `z.ipv4()` instead of
|
||
`z.string().<format>()`.
|
||
|
||
src/app/api/v1/campaigns/route.ts:28
|
||
|
||
src/app/api/v1/campaigns/route.ts:33-35
|
||
|
||
src/app/api/v1/products/route.ts:30
|
||
|
||
src/app/api/v1/referrals/route.ts:28-29
|
||
|
||
src/app/api/v1/reports/route.ts:27-29
|
||
|
||
src/app/api/v1/water-logs/route.ts:27-28
|
||
|
||
src/app/api/v1/water-logs/route.ts:34
|
||
|
||
src/lib/validation.ts:6-9
|
||
|
||
src/lib/validation.ts:19
|
||
|
||
src/lib/validation.ts:52-53
|
||
|
||
src/lib/validation.ts:105
|
||
|
||
src/lib/validation.ts:117
|
||
|
||
src/lib/validation.ts:126-127
|
||
|
||
src/lib/validation.ts:140
|
||
|
||
src/lib/validation.ts:149
|
||
|
||
src/lib/validation.ts:205
|
||
|
||
src/lib/validation.ts:218-219
|
||
|
||
src/lib/validation.ts:299-300
|
||
|
||
⚠ Accessibility: Handler on non-interactive element ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-noninteractive-element-interactions
|
||
Keyboard & screen reader users can't trigger this
|
||
`<dialog>` because it isn't interactive, so use a button or
|
||
link or add an interactive role.
|
||
→ Put interactions on a button or link, or add an
|
||
interactive role.
|
||
|
||
src/components/admin/MoreSheet.tsx:79
|
||
|
||
src/components/admin/orders/OrdersFilterButton.tsx:70
|
||
|
||
⚠ Accessibility: Autofocus on an element ×10
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-autofocus
|
||
`autoFocus` moves focus on load, which can disrupt screen
|
||
reader and keyboard users. Remove it and let users choose
|
||
where to focus.
|
||
→ Do not use `autoFocus`. It disorients users on load.
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:228
|
||
|
||
src/app/change-password/ChangePasswordForm.tsx:95
|
||
|
||
src/app/change-password/page.tsx:86
|
||
|
||
src/app/water/admin/login/WaterAdminPinClient.tsx:51
|
||
|
||
src/components/admin/CampaignListPanel.tsx:158
|
||
|
||
src/components/admin/HarvestReach/SegmentEditModal.tsx:85
|
||
|
||
src/components/admin/TemplateEditForm.tsx:177
|
||
|
||
src/components/route-trace/QRScanModal.tsx:282
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:91
|
||
|
||
src/components/water/WaterFieldClient.tsx:465
|
||
|
||
⚠ Performance: Large animated blur ×24
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-large-animated-blur
|
||
Large animated blurs can use significant GPU memory on
|
||
phones because blur(48px) gets heavier as the blur and
|
||
element grow. Use a smaller blur or a smaller element.
|
||
→ Keep the blur under 10px, or blur a smaller element. Big
|
||
blurs use a lot more GPU memory as the element grows
|
||
|
||
src/app/error.tsx:33
|
||
|
||
src/app/error.tsx:37
|
||
|
||
src/app/login/LoginClient.tsx:92
|
||
|
||
src/app/login/LoginClient.tsx:96
|
||
|
||
src/app/not-found.tsx:22
|
||
|
||
src/app/not-found.tsx:26
|
||
|
||
src/app/tuxedo/page.tsx:829
|
||
|
||
src/app/tuxedo/page.tsx:835
|
||
|
||
src/components/admin/BrandFeatureCards.tsx:69
|
||
|
||
src/components/landing/HeroSection.tsx:662
|
||
|
||
src/components/landing/HeroSection.tsx:898
|
||
|
||
src/components/landing/HeroSection.tsx:903
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:350
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:359
|
||
|
||
src/components/landing/LandingPageWrapper.tsx:368
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:473-474
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:529-530
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:241
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:250-251
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:214
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:223
|
||
|
||
⚠ Accessibility: Redundant ARIA role ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-redundant-roles
|
||
Screen reader users gain nothing from this `role` because
|
||
`<ul>` already acts as a `list`, so remove it.
|
||
→ Remove redundant `role` attributes so assistive tech
|
||
reads the element's native semantics without extra noise.
|
||
|
||
src/components/admin/CardList.tsx:10
|
||
|
||
src/components/admin/SideNavGroup.tsx:44
|
||
|
||
⚠ Accessibility: Gray text on colored background ×4
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-gray-on-colored-background
|
||
Your users see washed-out gray text (text-stone-400) on a
|
||
colored background (bg-red-50), so use white or a darker
|
||
shade of the background color.
|
||
→ Use white or near-white text, or a darker shade of the
|
||
background color. Gray text on colored backgrounds looks
|
||
washed out.
|
||
|
||
src/components/admin/ContactListPanel.tsx:355
|
||
|
||
src/components/admin/ContactListPanel.tsx:386
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:291
|
||
|
||
src/components/water/WaterFieldClient.tsx:557
|
||
|
||
⚠ Performance: Spread copy before sort() ×5
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/js-tosorted-immutable
|
||
This wastes work because [...array].sort() copies the array
|
||
just to sort it, so use array.toSorted() to sort without
|
||
the extra copy (ES2023)
|
||
→ Use `array.toSorted()` (ES2023) instead of
|
||
`[...array].sort()` so you sort without copying the array
|
||
first
|
||
|
||
src/components/admin/HarvestReach/AnalyticsDashboard.tsx:223
|
||
|
||
src/components/admin/StopTableClient.tsx:147
|
||
|
||
src/components/admin/StopsCalendarClient.tsx:594
|
||
|
||
src/components/admin/stops/StopsList.tsx:15
|
||
|
||
src/components/route-trace/RouteTraceDashboard.tsx:644
|
||
|
||
⚠ Maintainability: Large inline style object rebuilds every render ×16
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-inline-exhaustive-style
|
||
This inline style has 11 properties, which is hard to read
|
||
& rebuilds every render. Move it to a CSS class, CSS
|
||
module, or styled component.
|
||
→ Move the styles to a CSS class, CSS module, Tailwind
|
||
utilities, or a styled component. Big inline objects are
|
||
hard to read and rebuild on every update.
|
||
|
||
src/components/admin/CommandPalette.tsx:266
|
||
|
||
src/components/admin/CommandPalette.tsx:301
|
||
|
||
src/components/admin/CommandPalette.tsx:340
|
||
|
||
src/components/admin/CommandPalette.tsx:396
|
||
|
||
src/components/landing/FeaturesAndStats.tsx:569
|
||
|
||
src/components/landing/FeaturesAndStats.tsx:620
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:67
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:81
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:105
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:191
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:208
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:334
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:347
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:406
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:467
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:523
|
||
|
||
⚠ Maintainability: Pure function rebuilt every render ×37
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/prefer-module-scope-pure-function
|
||
`baseQuery` inside `AdminProductsPage` uses no local state
|
||
but is rebuilt on every render, so it wastes work & breaks
|
||
memoized children. Move it to the top of the file, outside
|
||
the component.
|
||
→ Move the function above the component, at the top of the
|
||
file. It doesn't use local state, so rebuilding it each
|
||
update is wasted work.
|
||
|
||
src/app/admin/products/page.tsx:64
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:689
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:842
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1091
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1378
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1608
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:173
|
||
|
||
src/app/api/water-logs/export/route.ts:58
|
||
|
||
src/app/login/LoginClient.tsx:75
|
||
|
||
src/app/tuxedo/page.tsx:494-500
|
||
|
||
src/components/admin/AddLocationModal.tsx:91
|
||
|
||
src/components/admin/AddLocationModal.tsx:96
|
||
|
||
src/components/admin/AdminHeader.tsx:89
|
||
|
||
src/components/admin/AdminSidebar.tsx:266
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:150
|
||
|
||
src/components/admin/ContactImportForm.tsx:208
|
||
|
||
src/components/admin/DashboardClient.tsx:94
|
||
|
||
src/components/admin/DashboardClient.tsx:98
|
||
|
||
src/components/admin/EditLocationModal.tsx:110
|
||
|
||
src/components/admin/EditLocationModal.tsx:115
|
||
|
||
src/components/admin/NewProductForm.tsx:76
|
||
|
||
src/components/admin/ProductEditForm.tsx:90
|
||
|
||
src/components/admin/ProductsClient.tsx:78
|
||
|
||
src/components/admin/ReportsDashboard.tsx:300
|
||
|
||
src/components/admin/TaxDashboard.tsx:228
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:225
|
||
|
||
src/components/admin/shared/DataTable.tsx:39
|
||
|
||
src/components/changelog/ChangelogFeed.tsx:69
|
||
|
||
src/components/landing/HeroSection.tsx:230
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx:97
|
||
|
||
src/components/notifications/InAppNotificationCenter.tsx:111
|
||
|
||
src/components/referral/ReferralSystem.tsx:55
|
||
|
||
src/components/water/WaterAdminClient.tsx:352
|
||
|
||
src/components/wholesale/admin/AddRecipientForm.tsx:10
|
||
|
||
src/context/CartContext.tsx:293
|
||
|
||
⚠ Maintainability: deslop/unused-dependency ×7
|
||
Unused dependency: `@gsap/react`
|
||
Unused dependency: `@upstash/ratelimit`
|
||
Unused dependency: `@upstash/redis`
|
||
Unused dependency: `next-auth`
|
||
Unused dependency: `posthog-js`
|
||
Unused dependency: `posthog-node`
|
||
Unused dependency: `square`
|
||
→ An unused dependency adds install time and supply-chain
|
||
surface without being used; remove it from package.json if
|
||
it is genuinely unused.
|
||
|
||
⚠ Maintainability: deslop/unused-dev-dependency ×2
|
||
Unused devDependency: `@lhci/cli`
|
||
Unused devDependency: `vite-tsconfig-paths`
|
||
→ An unused devDependency adds install time and
|
||
supply-chain surface without being used; remove it from
|
||
package.json if it is genuinely unused.
|
||
|
||
⚠ Maintainability: Large component is hard to read and change ×59
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-giant-component
|
||
Component "ImportCenterClient" is 390 lines long, which is
|
||
hard to read & change. Split it into a few smaller
|
||
components.
|
||
→ Pull each section into its own component so the parent is
|
||
easier to read, test, and change.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:30
|
||
|
||
src/app/admin/orders/[id]/page.tsx:32
|
||
|
||
src/app/admin/settings/billing/BillingClientPage.tsx:57
|
||
|
||
src/app/admin/settings/square-sync/SquareSyncSettingsClient.tsx:39
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:34
|
||
|
||
src/app/cart/CartClient.tsx:12
|
||
|
||
src/app/checkout/CheckoutClient.tsx:16
|
||
|
||
src/app/indian-river-direct/page.tsx:71
|
||
|
||
src/app/pricing/PricingClientPage.tsx:53
|
||
|
||
src/app/tuxedo/page.tsx:423
|
||
|
||
src/app/wholesale/portal/page.tsx:224
|
||
|
||
src/components/admin/AddStopModal.tsx:32
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:97
|
||
|
||
src/components/admin/AdminSidebar.tsx:139
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:187
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:58
|
||
|
||
src/components/admin/AdvancedPayments.tsx:112
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:24
|
||
|
||
src/components/admin/CampaignListPanel.tsx:323
|
||
|
||
src/components/admin/CommandPalette.tsx:165
|
||
|
||
src/components/admin/ContactImportForm.tsx:88
|
||
|
||
src/components/admin/ContactListPanel.tsx:127
|
||
|
||
src/components/admin/CreateUserModal.tsx:62
|
||
|
||
src/components/admin/DashboardClient.tsx:75
|
||
|
||
src/components/admin/EditStopModal.tsx:38
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:311
|
||
|
||
src/components/admin/LocationsTab.tsx:45
|
||
|
||
src/components/admin/NewProductForm.tsx:17
|
||
|
||
src/components/admin/NewStopForm.tsx:26
|
||
|
||
src/components/admin/OrderEditForm.tsx:57
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:34
|
||
|
||
src/components/admin/ProductEditForm.tsx:33
|
||
|
||
src/components/admin/ProductFormModal.tsx:82
|
||
|
||
src/components/admin/ProductsClient.tsx:40
|
||
|
||
src/components/admin/ReportsDashboard.tsx:188
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:18
|
||
|
||
src/components/admin/SettingsSections.tsx:85
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:34
|
||
|
||
src/components/admin/StopProductAssignment.tsx:43
|
||
|
||
src/components/admin/StopTableClient.tsx:89
|
||
|
||
src/components/admin/StopsCalendarClient.tsx:117
|
||
|
||
src/components/admin/TemplateEditForm.tsx:298
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:75
|
||
|
||
src/components/admin/UsersPage.tsx:116
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:69
|
||
|
||
src/components/admin/stops/StopsCalendar.tsx:74
|
||
|
||
src/components/landing/FeaturesAndStats.tsx:172
|
||
|
||
src/components/landing/HeroSection.tsx:16
|
||
|
||
src/components/landing/TestimonialsAndCTA.tsx:55
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:166
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:14
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:214
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:37
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:30
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:164
|
||
|
||
src/components/water/WaterAdminClient.tsx:263
|
||
|
||
src/components/water/WaterFieldClient.tsx:120
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:26
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:29
|
||
|
||
⚠ Performance: Overly precise SVG path values ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/rendering-svg-precision
|
||
Your users download extra bytes for SVG d precision they
|
||
can't see, so round it to 1 or 2 decimals.
|
||
→ Round path, points, and transform decimals to 1 or 2
|
||
digits. The extra precision adds bytes with no visible
|
||
difference.
|
||
|
||
src/app/admin/launch-checklist/page.tsx:125
|
||
|
||
src/app/admin/launch-checklist/page.tsx:131
|
||
|
||
⚠ Performance: .map().filter(Boolean) loops twice ×8
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/js-flatmap-filter
|
||
This loops over your list twice because
|
||
.map().filter(Boolean) makes two passes, so use .flatMap()
|
||
to change & drop items in one pass
|
||
→ Use `.flatMap(item => condition ? [value] : [])` to
|
||
change and drop items in one pass, instead of building a
|
||
throwaway array in between
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:308
|
||
|
||
src/components/admin/ContactImportForm.tsx:263
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:394
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPanel.tsx:449
|
||
|
||
src/components/admin/StopsCalendarClient.tsx:155
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:1184
|
||
|
||
src/components/admin/stops/StopsLocations.tsx:58
|
||
|
||
src/lib/column-detector.ts:255
|
||
|
||
⚠ Performance: Chained array iterations ×31
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/js-combine-iterations
|
||
This loops over your list twice because .filter().map()
|
||
makes two passes, so do it in one pass with .reduce() or a
|
||
for...of loop
|
||
→ Combine `.map().filter()` style chains into one pass with
|
||
`.reduce()` or a `for...of` loop, so you only loop over the
|
||
list once
|
||
|
||
public/sw.js:31
|
||
|
||
src/actions/ai-import.ts:335
|
||
|
||
src/actions/ai-import.ts:380
|
||
|
||
src/actions/ai-import.ts:403
|
||
|
||
src/actions/ai-import.ts:423
|
||
|
||
src/actions/dashboard.ts:198
|
||
|
||
src/actions/tax.ts:67
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:811-814
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1585
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClientPage.tsx:440
|
||
|
||
src/app/admin/v2/stops/page.tsx:264
|
||
|
||
src/app/api/wholesale/price-sheet/route.ts:76
|
||
|
||
src/app/api/wholesale/price-sheet/route.ts:146
|
||
|
||
src/app/cart/CartClient.tsx:65-68
|
||
|
||
src/app/cart/CartClient.tsx:139
|
||
|
||
src/app/cart/CartClient.tsx:317
|
||
|
||
src/app/checkout/CheckoutClient.tsx:277
|
||
|
||
src/app/roadmap/page.tsx:230
|
||
|
||
src/components/admin/AdminSidebar.tsx:186
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:804
|
||
|
||
src/components/admin/CommandPalette.tsx:126
|
||
|
||
src/components/admin/DashboardClient.tsx:166
|
||
|
||
src/components/admin/IntegrationsInner.tsx:318
|
||
|
||
src/components/admin/ShippingFulfillmentPanel.tsx:529
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:260
|
||
|
||
src/components/admin/stops/StopsLocations.tsx:61
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:761
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:251
|
||
|
||
src/context/CartContext.tsx:241
|
||
|
||
⚠ Bugs: Blocking side effect before response ×6
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/server-after-nonblocking
|
||
console.log() runs before the response, so your users wait
|
||
longer for it.
|
||
→ `import { after } from 'next/server'`, then wrap it:
|
||
`after(() => analytics.track(...))`. The response sends
|
||
right away.
|
||
|
||
src/actions/admin/password.ts:46
|
||
|
||
src/actions/admin/reset-admin.ts:85
|
||
|
||
src/actions/admin/reset-admin.ts:108
|
||
|
||
src/actions/admin/users.ts:133
|
||
|
||
src/actions/admin/users.ts:495
|
||
|
||
src/actions/auth-actions.ts:11
|
||
|
||
⚠ Bugs: Unversioned localStorage key ×3
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/client-localstorage-no-version
|
||
sessionStorage.setItem("pending_checkout",
|
||
JSON.stringify(...)) has no version, so changing the data
|
||
shape later crashes your users' saved sessions. Add one to
|
||
the key (e.g. "pending_checkout:v1").
|
||
→ Put a version in the storage key (e.g. "myKey:v1"). If
|
||
you change the data shape later, old saved data can be
|
||
ignored instead of crashing the app.
|
||
|
||
src/app/checkout/CheckoutClient.tsx:108
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:301
|
||
|
||
src/components/storefront/StripeExpressCheckout.tsx:167
|
||
|
||
⚠ Performance: Transition duration too long ×18
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-long-transition-duration
|
||
Your users wait through a sluggish 4000ms transition, so
|
||
keep UI transitions under 1000ms & save longer ones for big
|
||
page-load animations.
|
||
→ Keep UI transitions under 1s. Use about 100 to 150ms for
|
||
instant feedback, 200 to 300ms for state changes, and 300
|
||
to 500ms for layout. Save longer ones for big page-load
|
||
animations.
|
||
|
||
src/app/maintenance/page.tsx:8-9
|
||
|
||
src/components/landing/HeroSection.tsx:267
|
||
|
||
src/components/landing/HeroSection.tsx:272
|
||
|
||
src/components/landing/HeroSection.tsx:451
|
||
|
||
src/components/landing/HeroSection.tsx:465
|
||
|
||
src/components/landing/HeroSection.tsx:470
|
||
|
||
src/components/landing/HeroSection.tsx:478
|
||
|
||
src/components/landing/HeroSection.tsx:518
|
||
|
||
src/components/landing/HeroSection.tsx:532
|
||
|
||
src/components/landing/HeroSection.tsx:546
|
||
|
||
src/components/landing/HeroSection.tsx:576
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:686
|
||
|
||
src/components/route-trace/StatusBadge.tsx:68
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:215
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:224
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:402
|
||
|
||
src/components/transitions/LoadingFade.tsx:31
|
||
|
||
⚠ Maintainability: React 19 API migration can break callers ×3
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-react19-deprecated-apis
|
||
useContext is replaced by `use()` in React 19, which reads
|
||
context inside ifs & loops too, so switch to `import { use
|
||
} from 'react'`.
|
||
→ Pass `ref` as a normal prop on function components, since
|
||
`forwardRef` isn't needed in React 19. Replace
|
||
`useContext(X)` with `use(X)`. Only runs on React 19+
|
||
projects.
|
||
|
||
src/components/admin/Toast.tsx:3
|
||
|
||
src/components/admin/design-system/AdminSearchInput.tsx:3
|
||
|
||
src/context/CartContext.tsx:6
|
||
|
||
⚠ Bugs: Many related useState calls ×107
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/prefer-useReducer
|
||
12 useState calls in "ImportCenterClient" can each trigger
|
||
a separate render.
|
||
→ Group related state in `useReducer` so one logical update
|
||
does not fan out into separate renders.
|
||
|
||
src/app/admin/import/ImportCenterClient.tsx:30
|
||
|
||
src/app/admin/me/AdminMeClient.tsx:11
|
||
|
||
src/app/admin/products/import/page.tsx:19
|
||
|
||
src/app/admin/sales/import/page.tsx:17
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:558
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:652
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:784
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1045
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1325
|
||
|
||
src/app/admin/settings/ai/AIClient.tsx:1557
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:163
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClient.tsx:466
|
||
|
||
src/app/admin/settings/integrations/IntegrationsClientPage.tsx:112
|
||
|
||
src/app/admin/settings/square-sync/SquareSyncSettingsClient.tsx:39
|
||
|
||
src/app/admin/water-log/headgates/HeadgatesManager.tsx:34
|
||
|
||
src/app/admin/water-log/settings/page.tsx:28
|
||
|
||
src/app/admin/wholesale/WholesaleClient.tsx:36
|
||
|
||
src/app/cart/CartClient.tsx:12
|
||
|
||
src/app/checkout/CheckoutClient.tsx:16
|
||
|
||
src/app/indian-river-direct/about/page.tsx:17
|
||
|
||
src/app/indian-river-direct/contact/ContactClientPage.tsx:22
|
||
|
||
src/app/indian-river-direct/page.tsx:71
|
||
|
||
src/app/login/LoginClient.tsx:14
|
||
|
||
src/app/reset-password/page.tsx:6
|
||
|
||
src/app/tuxedo/page.tsx:423
|
||
|
||
src/app/wholesale/employee/page.tsx:31
|
||
|
||
src/app/wholesale/login/page.tsx:52
|
||
|
||
src/app/wholesale/portal/page.tsx:224
|
||
|
||
src/app/wholesale/register/page.tsx:34
|
||
|
||
src/components/admin/AIProviderPanel.tsx:99
|
||
|
||
src/components/admin/AbandonedCartDashboard.tsx:33
|
||
|
||
src/components/admin/AddLocationModal.tsx:14
|
||
|
||
src/components/admin/AddStopModal.tsx:32
|
||
|
||
src/components/admin/AdminOrdersPanel.tsx:102
|
||
|
||
src/components/admin/AdminStopsPanel.tsx:50
|
||
|
||
src/components/admin/AdvancedAIPanel.tsx:187
|
||
|
||
src/components/admin/AdvancedIntegrations.tsx:58
|
||
|
||
src/components/admin/AdvancedPayments.tsx:112
|
||
|
||
src/components/admin/AdvancedShipping.tsx:46
|
||
|
||
src/components/admin/AdvancedSquareSync.tsx:32
|
||
|
||
src/components/admin/AnalyticsDashboard.tsx:338
|
||
|
||
src/components/admin/BrandSettingsForm.tsx:30
|
||
|
||
src/components/admin/CampaignListPanel.tsx:333
|
||
|
||
src/components/admin/CommunicationSettingsForm.tsx:40
|
||
|
||
src/components/admin/ContactImportForm.tsx:88
|
||
|
||
src/components/admin/ContactListPanel.tsx:135
|
||
|
||
src/components/admin/CreateUserModal.tsx:62
|
||
|
||
src/components/admin/DriverPickupPanel.tsx:76
|
||
|
||
src/components/admin/EditLocationModal.tsx:30
|
||
|
||
src/components/admin/EditStopModal.tsx:38
|
||
|
||
src/components/admin/HarvestReach/CampaignComposerPage.tsx:311
|
||
|
||
src/components/admin/HarvestReach/MatchingCustomersPanel.tsx:45
|
||
|
||
src/components/admin/HarvestReach/SegmentBuilderPage.tsx:97
|
||
|
||
src/components/admin/HeadgateEditForm.tsx:24
|
||
|
||
src/components/admin/IntegrationsInner.tsx:114
|
||
|
||
src/components/admin/LocationsTab.tsx:45
|
||
|
||
src/components/admin/MessageCustomersSection.tsx:19
|
||
|
||
src/components/admin/MessageLogPanel.tsx:219
|
||
|
||
src/components/admin/NewProductForm.tsx:17
|
||
|
||
src/components/admin/NewStopForm.tsx:26
|
||
|
||
src/components/admin/OrderEditForm.tsx:57
|
||
|
||
src/components/admin/OrderPaymentSection.tsx:45
|
||
|
||
src/components/admin/PaymentSettingsForm.tsx:34
|
||
|
||
src/components/admin/ProductEditForm.tsx:33
|
||
|
||
src/components/admin/ProductFormModal.tsx:93
|
||
|
||
src/components/admin/ProductsClient.tsx:50
|
||
|
||
src/components/admin/ReportsDashboard.tsx:198
|
||
|
||
src/components/admin/ScheduleImportModal.tsx:18
|
||
|
||
src/components/admin/SettingsSections.tsx:85
|
||
|
||
src/components/admin/ShippingFulfillmentPanel.tsx:92
|
||
|
||
src/components/admin/ShippingFulfillmentPanel.tsx:570
|
||
|
||
src/components/admin/ShippingSettingsForm.tsx:39
|
||
|
||
src/components/admin/SquareSyncWidget.tsx:12
|
||
|
||
src/components/admin/StopDetailModal.tsx:23
|
||
|
||
src/components/admin/StopEditForm.tsx:34
|
||
|
||
src/components/admin/StopMessagingForm.tsx:23
|
||
|
||
src/components/admin/StopProductAssignment.tsx:48
|
||
|
||
src/components/admin/StopTableClient.tsx:89
|
||
|
||
src/components/admin/TaxDashboard.tsx:135
|
||
|
||
src/components/admin/TemplateEditForm.tsx:306
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:148
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:758
|
||
|
||
src/components/admin/TimeTrackingAdminPanel.tsx:850
|
||
|
||
src/components/admin/TimeTrackingSettingsClient.tsx:75
|
||
|
||
src/components/admin/UsersPage.tsx:116
|
||
|
||
src/components/admin/WaterLogAdminPanel.tsx:75
|
||
|
||
src/components/admin/WaterLogEntryEditForm.tsx:30
|
||
|
||
src/components/admin/WaterUserEditForm.tsx:23
|
||
|
||
src/components/admin/WelcomeSequenceDashboard.tsx:24
|
||
|
||
src/components/marketing/WaitlistForm.tsx:10
|
||
|
||
src/components/route-trace/AdminLookupPage.tsx:41
|
||
|
||
src/components/route-trace/FsmaReportModal.tsx:166
|
||
|
||
src/components/route-trace/LotCreateForm.tsx:26
|
||
|
||
src/components/route-trace/LotCreateModal.tsx:14
|
||
|
||
src/components/route-trace/LotDetailPanel.tsx:222
|
||
|
||
src/components/route-trace/QRScanModal.tsx:57
|
||
|
||
src/components/route-trace/QuickNewLotModal.tsx:34
|
||
|
||
src/components/route-trace/StickerPreviewModal.tsx:36
|
||
|
||
src/components/storefront/StripeExpressCheckout.tsx:59
|
||
|
||
src/components/storefront/SweetCornProductPage.tsx:37
|
||
|
||
src/components/time-tracking/TimeTrackingFieldClient.tsx:174
|
||
|
||
src/components/water/WaterAdminClient.tsx:263
|
||
|
||
src/components/water/WaterFieldClient.tsx:120
|
||
|
||
src/components/wholesale/admin/CustomersTab.tsx:33
|
||
|
||
src/components/wholesale/admin/OrdersTab.tsx:29
|
||
|
||
src/components/wholesale/admin/ProductsTab.tsx:18
|
||
|
||
src/context/CartContext.tsx:66
|
||
|
||
⚠ Maintainability: Multiple components in one file ×9
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-multi-comp
|
||
This file declares several components, so each component is
|
||
harder to find, test, and change.
|
||
→ Move secondary components into their own files so each
|
||
component stays easier to find, test, and change.
|
||
|
||
src/components/admin/design-system/AdminBadge.tsx:159
|
||
|
||
src/components/admin/design-system/AdminBadge.tsx:177
|
||
|
||
src/components/admin/design-system/AdminCard.tsx:31
|
||
|
||
src/components/admin/design-system/AdminCard.tsx:44
|
||
|
||
src/components/admin/design-system/AdminFilterTabs.tsx:141
|
||
|
||
src/components/admin/design-system/AdminFilterTabs.tsx:179
|
||
|
||
src/components/admin/design-system/AdminFilterTabs.tsx:185
|
||
|
||
src/components/admin/design-system/AdminFilterTabs.tsx:191
|
||
|
||
src/components/admin/design-system/AdminFilterTabs.tsx:197
|
||
|
||
⚠ Maintainability: Non-component export in component file
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/only-export-components
|
||
This file exports non-components, so Fast Refresh can't
|
||
safely preserve component state.
|
||
→ Move non-component exports out of component files so Fast
|
||
Refresh can preserve component state instead of
|
||
full-reloading.
|
||
|
||
src/components/notifications/ToastNotification.tsx:128
|
||
|
||
⚠ Performance: Bouncy easing animation
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-inline-bounce-easing
|
||
Your users see a dated, tacky animate-bounce, so use a
|
||
subtle ease-out transform for a smoother finish.
|
||
→ Use `cubic-bezier(0.16, 1, 0.3, 1)` (ease-out-expo) for a
|
||
natural finish. Real objects don't bounce.
|
||
|
||
src/components/storefront/TuxedoVideoHero.tsx:400
|
||
|
||
⚠ Performance: Animating scale from zero ×12
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/no-scale-from-zero
|
||
This looks abrupt to your users because scale: 0 pops the
|
||
element in from a single point, so use scale: 0.95 with
|
||
opacity: 0 for a smoother entrance
|
||
→ Use `initial={{ scale: 0.95, opacity: 0 }}`. Elements
|
||
should gently shrink and fade, not vanish into a point
|
||
|
||
src/app/indian-river-direct/about/error.tsx:27
|
||
|
||
src/app/indian-river-direct/contact/error.tsx:27
|
||
|
||
src/app/indian-river-direct/error.tsx:29
|
||
|
||
src/app/indian-river-direct/faq/error.tsx:27
|
||
|
||
src/app/indian-river-direct/stops/[id]/error.tsx:27
|
||
|
||
src/app/tuxedo/about/error.tsx:22
|
||
|
||
src/app/tuxedo/contact/error.tsx:22
|
||
|
||
src/app/tuxedo/error.tsx:23
|
||
|
||
src/app/tuxedo/faq/error.tsx:22
|
||
|
||
src/app/tuxedo/stops/[id]/error.tsx:22
|
||
|
||
src/components/storefront/QuickCartSheet.tsx:210
|
||
|
||
src/components/storefront/StorefrontHeader.tsx:129
|
||
|
||
⚠ Security: Unescaped JSON in HTML or script sink ×6
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/unsafe-json-in-html
|
||
JSON.stringify is embedded in HTML/script markup without
|
||
HTML-escaping; data containing `</script>` or `<` breaks
|
||
out and becomes XSS.
|
||
→ JSON.stringify does not HTML-escape, so a `</script>` (or
|
||
`<`) in the data breaks out and becomes XSS. Use an
|
||
HTML-safe serializer (serialize-javascript, devalue) or
|
||
escape `<`, `>`, and `&`, or pass data via a JSON `<script
|
||
type="application/json">` read with JSON.parse.
|
||
|
||
src/app/indian-river-direct/faq/layout.tsx:86
|
||
|
||
src/app/page.tsx:126
|
||
|
||
src/app/tuxedo/faq/layout.tsx:134-136
|
||
|
||
src/app/tuxedo/faq/layout.tsx:140
|
||
|
||
src/app/tuxedo/faq/layout.tsx:144
|
||
|
||
⚠ Security: Auth cookie missing HttpOnly protection ×3
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/insecure-session-cookie
|
||
An auth/session cookie is exposed to JavaScript (set via
|
||
document.cookie, with httpOnly: false, or without cookie
|
||
options), letting an XSS payload steal it.
|
||
→ Set auth/session cookies server-side with `httpOnly:
|
||
true`, `secure: true`, and `sameSite`. Cookies set via
|
||
`document.cookie` or with `httpOnly: false` are readable by
|
||
any XSS payload and can be stolen.
|
||
|
||
src/app/login/LoginClient.tsx:77
|
||
|
||
src/app/wholesale/employee/page.tsx:83
|
||
|
||
src/app/wholesale/portal/page.tsx:561
|
||
|
||
⚠ Accessibility: Dialog without accessible name ×2
|
||
Learn more: https://react.doctor/docs/rules/react-doctor/dialog-has-accessible-name
|
||
This dialog has no accessible name, so screen readers
|
||
announce it as just “dialog.” Add `aria-label` or point
|
||
`aria-labelledby` at its heading.
|
||
→ Give every `<dialog>` / `role="dialog"` an accessible
|
||
name with `aria-label` or `aria-labelledby` (referencing
|
||
the dialog's title element).
|
||
|
||
src/components/admin/MoreSheet.tsx:79
|
||
|
||
src/components/admin/orders/OrdersFilterButton.tsx:70
|
||
|
||
|
||
────────────────────────────────────────────────────────────
|
||
|
||
All 2821 issues
|
||
|
||
Security › 4 errors, 19 warnings
|
||
Bugs › 145 errors, 1045 warnings
|
||
Performance › 297 warnings
|
||
Accessibility › 869 warnings
|
||
Maintainability › 442 warnings
|
||
|
||
⚠ Migration-scale change: sample before you sweep
|
||
Button missing explicit type ×527 across 149 files
|
||
deslop/unused-file ×114 across 114 files
|
||
Control missing accessible label ×444 across 108 files
|
||
+5 more rules at this scale
|
||
Fixing all of them at once is hard to review and prone to
|
||
subtle mistakes across the whole repo. Fix a representative
|
||
few first and confirm the recipe holds. Then get the code
|
||
owner's sign-off before changing the rest.
|
||
Scope it down one area at a time: npx react-doctor@latest <path>
|
||
|
||
┌─────┐ 7 / 100 Critical
|
||
│ x x │ ████▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
||
│ ▽ │ React Doctor (https://react.doctor)
|
||
└─────┘
|
||
|
||
You could improve +6% by fixing the top 3 issues
|
||
Full diagnostics written to /tmp/react-doctor-c8e6f28b-e833-4dc5-9a50-41a9fefe65ba
|
||
|
||
────────────────────────────────────────────────────────────
|
||
|
||
Share: https://react.doctor/share?p=route-commerce-platform&s=7&e=149&w=2672&f=423
|
||
Tell others how you did on socials
|
||
|
||
Docs: https://react.doctor/docs
|
||
Learn more about fixing issues, setting up CI/CD, and
|
||
configuring rules with a config file
|
||
|
||
GitHub: https://github.com/millionco/react-doctor
|
||
Report issues and star the repository!
|
||
|