From cc540297bfdebad72227c6ea92fdf18dc9aa9a56 Mon Sep 17 00:00:00 2001 From: shafi54 <108669266+shafi-aviz@users.noreply.github.com> Date: Sun, 16 Aug 2026 15:45:05 +0530 Subject: [PATCH] enh --- .commandcode/settings.json | 13 +- .commandcode/taste/taste/taste.md | 10 +- apps/admin-ui/.expo/types/router.d.ts | 6 +- .../app/(drawer)/dashboard/products/index.tsx | 230 ++++++++-------- apps/user-ui/components/AddressSelector.tsx | 164 ------------ apps/user-ui/components/CustomHeader.tsx | 58 ---- apps/user-ui/components/NextOrderGlimpse.tsx | 249 +++++++++++------- apps/user-ui/components/ProductDetail.tsx | 1 - apps/user-ui/components/ProfileChecker.tsx | 49 ---- apps/user-ui/components/UserAddressHeader.tsx | 45 ---- .../components/icons/OrderAgainIcon.tsx | 21 -- apps/user-ui/components/ui/IconSymbol.ios.tsx | 32 --- apps/user-ui/components/ui/IconSymbol.tsx | 41 --- .../components/ui/TabBarBackground.ios.tsx | 19 -- .../components/ui/TabBarBackground.tsx | 6 - apps/user-ui/hooks/useCurrentUserId.ts | 13 - apps/user-ui/hooks/useHideDrawerHeader.ts | 26 -- apps/user-ui/hooks/usePhonepeSdk.ts | 34 --- apps/user-ui/hooks/useThemeColor.ts | 21 -- apps/user-ui/services/axios-user-ui.ts | 61 ----- docs/common-ui-dependency-audit.md | 55 ++++ docs/user-ui-cart-management.md | 182 +++++++++++++ packages/ui/hooks/useIsDevMode.ts | 8 - packages/ui/hooks/usePagination.tsx | 96 ------- packages/ui/index.ts | 27 +- packages/ui/src/components/ImageGallery.tsx | 71 ----- .../src/components/ImageGalleryWithDelete.tsx | 106 -------- .../ui/src/components/PaginatedDataTable.tsx | 76 ------ packages/ui/src/components/data-table.tsx | 76 ------ packages/ui/src/components/tab-view.tsx | 26 -- packages/ui/src/lib/constants.ts | 32 --- packages/ui/src/roles-dropdown.tsx | 16 -- 32 files changed, 535 insertions(+), 1335 deletions(-) delete mode 100644 apps/user-ui/components/AddressSelector.tsx delete mode 100644 apps/user-ui/components/CustomHeader.tsx delete mode 100644 apps/user-ui/components/ProfileChecker.tsx delete mode 100644 apps/user-ui/components/UserAddressHeader.tsx delete mode 100644 apps/user-ui/components/icons/OrderAgainIcon.tsx delete mode 100755 apps/user-ui/components/ui/IconSymbol.ios.tsx delete mode 100755 apps/user-ui/components/ui/IconSymbol.tsx delete mode 100755 apps/user-ui/components/ui/TabBarBackground.ios.tsx delete mode 100755 apps/user-ui/components/ui/TabBarBackground.tsx delete mode 100755 apps/user-ui/hooks/useCurrentUserId.ts delete mode 100755 apps/user-ui/hooks/useHideDrawerHeader.ts delete mode 100755 apps/user-ui/hooks/usePhonepeSdk.ts delete mode 100755 apps/user-ui/hooks/useThemeColor.ts delete mode 100644 apps/user-ui/services/axios-user-ui.ts create mode 100644 docs/common-ui-dependency-audit.md create mode 100644 docs/user-ui-cart-management.md delete mode 100644 packages/ui/hooks/useIsDevMode.ts delete mode 100644 packages/ui/hooks/usePagination.tsx delete mode 100755 packages/ui/src/components/ImageGallery.tsx delete mode 100644 packages/ui/src/components/ImageGalleryWithDelete.tsx delete mode 100755 packages/ui/src/components/PaginatedDataTable.tsx delete mode 100755 packages/ui/src/components/data-table.tsx delete mode 100644 packages/ui/src/components/tab-view.tsx delete mode 100755 packages/ui/src/roles-dropdown.tsx diff --git a/.commandcode/settings.json b/.commandcode/settings.json index 2668a61..435ab2f 100644 --- a/.commandcode/settings.json +++ b/.commandcode/settings.json @@ -8,7 +8,18 @@ "Shell(cp:*)", "Shell(rm:*)", "Shell(ls:*)", - "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/admin-ui && ls \"app/(drawer)\" 2>/dev/null; echo \"---\"; find app -name \"create.tsx\" -path \"*coupon*\" 2>/dev/null)" + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/admin-ui && ls \"app/(drawer)\" 2>/dev/null; echo \"---\"; find app -name \"create.tsx\" -path \"*coupon*\" 2>/dev/null)", + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/user-ui && echo \"=== verify zero external refs for each dead file ===\" && for f in \"ProfileChecker\" \"UserAddressHeader\" \"AddressSelector\" \"OrderAgainIcon\" \"usePhonepeSdk\" \"useHideDrawerHeader\" \"useCurrentUserId\" \"useThemeColor\" \"IconSymbol\" \"TabBarBackground\" \"axios-user-ui\"; do refs=$(grep -rn \"$f\" --include=\"*.tsx\" --include=\"*.ts\" . 2>/dev/null | grep -v node_modules | grep -vE \"components/ProfileChecker|components/UserAddressHeader|components/AddressSelector|icons/OrderAgainIcon|hooks/usePhonepeSdk|hooks/useHideDrawerHeader|hooks/useCurrentUserId|hooks/useThemeColor|components/ui/IconSymbol|components/ui/TabBarBackground|services/axios-user-ui\" | wc -l | tr -d ' '); echo \"$f: $refs external refs\"; done)", + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && echo \"=== usage count per export across apps (excluding packages/ui itself) ===\" && for name in RolesDropdown StorageService ROLE_NAMES ROLE_DISPLAY_NAMES ROLE_OPTIONS BUSINESS_ROLE_OPTIONS REFUND_STATUS MyButton MyTextButton MyTextInput BottomDialog LoadingDialog MyText MyTouchableOpacity ConfirmationDialog RawBottomDialog DatePicker BottomDropdown ImageViewerURI ImageCarousel ImageGallery ImageGalleryWithDelete ImageUploader ImageUploaderNeo ProfileImage Checkbox AppContainer SearchBar DataTable Quantifier MiniQuantifier TabViewWrapper MyFlatList useFocusCallback useManualRefresh useDrawerTitle useMarkDataFetchers useIsDevMode usePagination DateTimePickerMod RefreshProvider useRefresh MyStatusBar updateStatusBarColor useStatusBarStore; do count=$(grep -rn \"\\b$name\\b\" apps/user-ui apps/admin-ui apps/web-ui apps/fallback-ui --include=\"*.tsx\" --include=\"*.ts\" 2>/dev/null | grep -v node_modules | wc -l | tr -d ' '); echo \"$name: $count\"; done)", + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && echo \"=== check usage inside packages/ui (internal use) ===\" && for name in RolesDropdown ROLE_DISPLAY_NAMES ROLE_OPTIONS BUSINESS_ROLE_OPTIONS MyTextButton ImageGallery ImageGalleryWithDelete DataTable TabViewWrapper useIsDevMode usePagination useRefresh useStatusBarStore; do count=$(grep -rn \"\\b$name\\b\" packages/ui --include=\"*.tsx\" --include=\"*.ts\" 2>/dev/null | grep -v node_modules | grep -v \"index.ts\" | wc -l | tr -d ' '); echo \"$name: $count internal\"; done)", + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/dumps && echo \"=== lines 7890-7910 (product_skus start) ===\" && sed -n '7890,7910p' local_8_aug.sql && echo \"=== lines 8330-8345 (product_info start) ===\" && sed -n '8330,8345p' local_8_aug.sql && echo \"=== total lines ===\" && wc -l local_8_aug.sql && echo \"=== where does product_info block end? next CREATE/other marker ===\" && grep -nE \"CREATE TABLE|^INSERT INTO \\\"product_info\\\"|^INSERT INTO \\`product_info\\`|^INSERT INTO product_info\" local_8_aug.sql | sed -n '25,40p')", + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/dumps && echo \"=== product_info block: from 8334 to next CREATE TABLE after it ===\" && awk 'NR>=8334 && /^CREATE TABLE/ {print NR\": \"$0; exit}' local_8_aug.sql && echo \"=== where do product_skus INSERTs start/end ===\" && grep -nE \"^INSERT INTO \\`?product_skus\\`?|^INSERT INTO \\\"product_skus\\\"\" local_8_aug.sql | head && echo \"=== where do sku_features/product_market_stats/product_info INSERTs start ===\" && grep -nE \"^INSERT INTO \\`?(product_skus|sku_features|product_market_stats|product_info)\\`?\" local_8_aug.sql | head && echo \"=== what comes right after product_info INSERTs (next table or marker) ===\" && awk 'NR>8334 && /^CREATE TABLE/ {print NR\": \"$0}' local_8_aug.sql | head)", + "Shell(awk:*)", + "Shell(echo:*)", + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/dumps && python3 - <<'PY' # Move the product_info block (CREATE + INSERTs) above product_skus. with open('local_8_aug.sql', 'r') as f: lines = f.readlines() # 1-indexed boundaries pi_start = 8334 - 1 # CREATE TABLE product_info pi_end = 8478 # exclusive (up to line 8478 inclusive) -> slice [8333:8478] sku_start = 7900 - 1 # line where product_skus CREATE begins block = lines[pi_start:pi_end] # Remove the product_info block new_lines = lines[:pi_start] + lines[pi_end:] # Re-insert before product_skus (its index may have shifted by -len(block)) insert_at = sku_start new_lines = new_lines[:insert_at] + block + new_lines[insert_at:] with open('local_8_aug.sql', 'w') as f: f.writelines(new_lines) print(f\"Moved product_info block (lines {pi_start+1}-{pi_end}) to before line {sku_start+1}\") PY echo \"=== verify new order ===\" && grep -nE 'CREATE TABLE .(product_info|product_skus|sku_features|product_market_stats|cart_items).' local_8_aug.sql)", + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/dumps && echo \"=== order: product_info BEFORE product_skus? ===\" && grep -nE '^CREATE TABLE' local_8_aug.sql | grep -E \"product_info|product_skus|sku_features|product_market_stats|cart_items\" && echo \"=== doc check: every REFERENCES has parent CREATE before it ===\" && grep -nE '^CREATE TABLE|REFERENCES' local_8_aug.sql | grep -E \"REFERENCES\" | grep -oE \"REFERENCES \\`?[a-z_]+\" | sort | uniq -c)", + "Shell(sqlite3:*)", + "Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/dumps && sqlite3 :memory: <<'EOF' PRAGMA foreign_keys=ON; BEGIN; .read local_8_aug.sql COMMIT; EOF echo \"exit: $?\")" ], "deny": [], "defaultMode": "default" diff --git a/.commandcode/taste/taste/taste.md b/.commandcode/taste/taste/taste.md index 6952e7f..dd6b4da 100644 --- a/.commandcode/taste/taste/taste.md +++ b/.commandcode/taste/taste/taste.md @@ -19,5 +19,13 @@ - Prefers test plans written for a non-technical audience, using plain-language, click-by-click instructions ("tap this", "type that", "check there") rather than technical terms or API names. Confidence: 0.9 - When updating or creating a document, prefers the agent first compare it against existing source documents, identify missing items or gaps, and add them in the same established format. Confidence: 0.9 - Dislikes nested headers in mobile/drawer navigation; prefers a single, shared header (e.g., the drawer header) and relies on device back buttons or gestures for returning to previous screens. Confidence: 0.9 -- After reviewing a presented plan, prefers brief, action-oriented approval (e.g., "nice. go ahead") before implementation proceeds. Confidence: 0.6 +- After reviewing a presented plan, prefers brief, action-oriented approval (e.g., "nice. go ahead") before implementation proceeds. Confidence: 0.7 - Wants feature parity maintained between the web-ui and user-ui apps (port logic/data patterns, rebuild UI per platform). Confidence: 0.85 +- Prefers dead-code audits to be documented in a markdown file. Confidence: 0.8 +- Prefers detailed technical documentation of system architecture, data models, flows, and integrations in markdown format. Confidence: 0.8 +- Wants edge cases explicitly enumerated when documenting or analyzing existing code/systems. Confidence: 0.8 +- Values end-to-end analysis of features (architecture, data model, flows, integrations, and edge cases) when asked to explain how something works. Confidence: 0.7 +- Prefers unifying parallel data structures into a single instance rather than maintaining separate ones (e.g., one cart for flash and regular items instead of separate flash/regular carts). Confidence: 0.9 +- Prefers using sentinel values in existing fields (e.g., slotId = 0) to distinguish special-case items rather than creating separate fields or structures. Confidence: 0.9 +- Prefers handling special-case logic locally in the relevant component/file rather than globally or via parallel flows. Confidence: 0.85 +- Prefers lazy/virtualized list rendering (e.g., FlatList) for long lists, rather than rendering all items at once. Confidence: 0.8 diff --git a/apps/admin-ui/.expo/types/router.d.ts b/apps/admin-ui/.expo/types/router.d.ts index 6390fc7..e2dc4a9 100644 --- a/apps/admin-ui/.expo/types/router.d.ts +++ b/apps/admin-ui/.expo/types/router.d.ts @@ -6,9 +6,9 @@ export * from 'expo-router'; declare module 'expo-router' { export namespace ExpoRouter { export interface __routes { - hrefInputParams: { pathname: Router.RelativePathString, params?: Router.UnknownInputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownInputParams } | { pathname: `/`; params?: Router.UnknownInputParams; } | { pathname: `/login`; params?: Router.UnknownInputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/complaints` | `/complaints`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/coupons/create` | `/coupons/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/coupons` | `/coupons`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/coupons/reserved-coupons` | `/coupons/reserved-coupons`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/customize-app/all-items-order` | `/customize-app/all-items-order`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/customize-app` | `/customize-app`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/customize-app/popular-items` | `/customize-app/popular-items`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard` | `/dashboard`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard-banners/create` | `/dashboard-banners/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard-banners` | `/dashboard-banners`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/manage-orders` | `/manage-orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/manage-orders/delivery-sequences` | `/manage-orders/delivery-sequences`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/manage-orders/orders` | `/manage-orders/orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/prices-overview` | `/prices-overview`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-groupings/create` | `/product-groupings/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-groupings` | `/product-groupings`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-tags/add` | `/product-tags/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-tags` | `/product-tags`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-tags/edit` | `/product-tags/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/products/add` | `/products/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/products/edit` | `/products/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/products` | `/products`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/rebalance-orders` | `/rebalance-orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/send-notifications` | `/send-notifications`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/slots/add` | `/slots/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/slots` | `/slots`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/slots/slot-details` | `/slots/slot-details`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/stores/add` | `/stores/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/stores/edit` | `/stores/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/stores` | `/stores`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/user-management` | `/user-management`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/users` | `/users`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/vendor-snippets` | `/vendor-snippets`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/coupons/edit/[id]` | `/coupons/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard-banners/edit/[id]` | `/dashboard-banners/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/manage-orders/order-details/[id]` | `/manage-orders/order-details/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/product-groupings/edit/[id]` | `/product-groupings/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/products/detail/[id]` | `/products/detail/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/slots/edit/[id]` | `/slots/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/user-management/[id]` | `/user-management/[id]`, params: Router.UnknownInputParams & { id: string | number; } }; - hrefOutputParams: { pathname: Router.RelativePathString, params?: Router.UnknownOutputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownOutputParams } | { pathname: `/`; params?: Router.UnknownOutputParams; } | { pathname: `/login`; params?: Router.UnknownOutputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/complaints` | `/complaints`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/coupons/create` | `/coupons/create`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/coupons` | `/coupons`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/coupons/reserved-coupons` | `/coupons/reserved-coupons`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/customize-app/all-items-order` | `/customize-app/all-items-order`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/customize-app` | `/customize-app`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/customize-app/popular-items` | `/customize-app/popular-items`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard` | `/dashboard`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard-banners/create` | `/dashboard-banners/create`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard-banners` | `/dashboard-banners`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/manage-orders` | `/manage-orders`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/manage-orders/delivery-sequences` | `/manage-orders/delivery-sequences`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/manage-orders/orders` | `/manage-orders/orders`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/prices-overview` | `/prices-overview`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/product-groupings/create` | `/product-groupings/create`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/product-groupings` | `/product-groupings`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/product-tags/add` | `/product-tags/add`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/product-tags` | `/product-tags`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/product-tags/edit` | `/product-tags/edit`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/products/add` | `/products/add`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/products/edit` | `/products/edit`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/products` | `/products`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/rebalance-orders` | `/rebalance-orders`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/send-notifications` | `/send-notifications`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/slots/add` | `/slots/add`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/slots` | `/slots`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/slots/slot-details` | `/slots/slot-details`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/stores/add` | `/stores/add`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/stores/edit` | `/stores/edit`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/stores` | `/stores`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/user-management` | `/user-management`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/users` | `/users`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/vendor-snippets` | `/vendor-snippets`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/coupons/edit/[id]` | `/coupons/edit/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/dashboard-banners/edit/[id]` | `/dashboard-banners/edit/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/manage-orders/order-details/[id]` | `/manage-orders/order-details/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/product-groupings/edit/[id]` | `/product-groupings/edit/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/products/detail/[id]` | `/products/detail/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/slots/edit/[id]` | `/slots/edit/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/user-management/[id]` | `/user-management/[id]`, params: Router.UnknownOutputParams & { id: string; } }; - href: Router.RelativePathString | Router.ExternalPathString | `/${`?${string}` | `#${string}` | ''}` | `/login${`?${string}` | `#${string}` | ''}` | `/_sitemap${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/complaints${`?${string}` | `#${string}` | ''}` | `/complaints${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/coupons/create${`?${string}` | `#${string}` | ''}` | `/coupons/create${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/coupons${`?${string}` | `#${string}` | ''}` | `/coupons${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/coupons/reserved-coupons${`?${string}` | `#${string}` | ''}` | `/coupons/reserved-coupons${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/customize-app/all-items-order${`?${string}` | `#${string}` | ''}` | `/customize-app/all-items-order${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/customize-app${`?${string}` | `#${string}` | ''}` | `/customize-app${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/customize-app/popular-items${`?${string}` | `#${string}` | ''}` | `/customize-app/popular-items${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard${`?${string}` | `#${string}` | ''}` | `/dashboard${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard-banners/create${`?${string}` | `#${string}` | ''}` | `/dashboard-banners/create${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard-banners${`?${string}` | `#${string}` | ''}` | `/dashboard-banners${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/manage-orders${`?${string}` | `#${string}` | ''}` | `/manage-orders${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/manage-orders/delivery-sequences${`?${string}` | `#${string}` | ''}` | `/manage-orders/delivery-sequences${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/manage-orders/orders${`?${string}` | `#${string}` | ''}` | `/manage-orders/orders${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/prices-overview${`?${string}` | `#${string}` | ''}` | `/prices-overview${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/product-groupings/create${`?${string}` | `#${string}` | ''}` | `/product-groupings/create${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/product-groupings${`?${string}` | `#${string}` | ''}` | `/product-groupings${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/product-tags/add${`?${string}` | `#${string}` | ''}` | `/product-tags/add${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/product-tags${`?${string}` | `#${string}` | ''}` | `/product-tags${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/product-tags/edit${`?${string}` | `#${string}` | ''}` | `/product-tags/edit${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/products/add${`?${string}` | `#${string}` | ''}` | `/products/add${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/products/edit${`?${string}` | `#${string}` | ''}` | `/products/edit${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/products${`?${string}` | `#${string}` | ''}` | `/products${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/rebalance-orders${`?${string}` | `#${string}` | ''}` | `/rebalance-orders${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/send-notifications${`?${string}` | `#${string}` | ''}` | `/send-notifications${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/slots/add${`?${string}` | `#${string}` | ''}` | `/slots/add${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/slots${`?${string}` | `#${string}` | ''}` | `/slots${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/slots/slot-details${`?${string}` | `#${string}` | ''}` | `/slots/slot-details${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/stores/add${`?${string}` | `#${string}` | ''}` | `/stores/add${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/stores/edit${`?${string}` | `#${string}` | ''}` | `/stores/edit${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/stores${`?${string}` | `#${string}` | ''}` | `/stores${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/user-management${`?${string}` | `#${string}` | ''}` | `/user-management${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/users${`?${string}` | `#${string}` | ''}` | `/users${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/vendor-snippets${`?${string}` | `#${string}` | ''}` | `/vendor-snippets${`?${string}` | `#${string}` | ''}` | { pathname: Router.RelativePathString, params?: Router.UnknownInputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownInputParams } | { pathname: `/`; params?: Router.UnknownInputParams; } | { pathname: `/login`; params?: Router.UnknownInputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/complaints` | `/complaints`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/coupons/create` | `/coupons/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/coupons` | `/coupons`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/coupons/reserved-coupons` | `/coupons/reserved-coupons`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/customize-app/all-items-order` | `/customize-app/all-items-order`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/customize-app` | `/customize-app`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/customize-app/popular-items` | `/customize-app/popular-items`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard` | `/dashboard`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard-banners/create` | `/dashboard-banners/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard-banners` | `/dashboard-banners`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/manage-orders` | `/manage-orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/manage-orders/delivery-sequences` | `/manage-orders/delivery-sequences`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/manage-orders/orders` | `/manage-orders/orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/prices-overview` | `/prices-overview`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-groupings/create` | `/product-groupings/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-groupings` | `/product-groupings`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-tags/add` | `/product-tags/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-tags` | `/product-tags`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/product-tags/edit` | `/product-tags/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/products/add` | `/products/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/products/edit` | `/products/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/products` | `/products`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/rebalance-orders` | `/rebalance-orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/send-notifications` | `/send-notifications`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/slots/add` | `/slots/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/slots` | `/slots`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/slots/slot-details` | `/slots/slot-details`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/stores/add` | `/stores/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/stores/edit` | `/stores/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/stores` | `/stores`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/user-management` | `/user-management`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/users` | `/users`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/vendor-snippets` | `/vendor-snippets`; params?: Router.UnknownInputParams; } | `${'/(drawer)'}/coupons/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/coupons/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard-banners/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/dashboard-banners/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/manage-orders/order-details/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/manage-orders/order-details/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/product-groupings/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/product-groupings/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/products/detail/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/products/detail/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/slots/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/slots/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/user-management/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/user-management/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | { pathname: `${'/(drawer)'}/coupons/edit/[id]` | `/coupons/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard-banners/edit/[id]` | `/dashboard-banners/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/manage-orders/order-details/[id]` | `/manage-orders/order-details/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/product-groupings/edit/[id]` | `/product-groupings/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/products/detail/[id]` | `/products/detail/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/slots/edit/[id]` | `/slots/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/user-management/[id]` | `/user-management/[id]`, params: Router.UnknownInputParams & { id: string | number; } }; + hrefInputParams: { pathname: Router.RelativePathString, params?: Router.UnknownInputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownInputParams } | { pathname: `/`; params?: Router.UnknownInputParams; } | { pathname: `/login`; params?: Router.UnknownInputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard` | `/dashboard`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/complaints` | `/dashboard/complaints`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons/create` | `/dashboard/coupons/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons` | `/dashboard/coupons`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons/reserved-coupons` | `/dashboard/coupons/reserved-coupons`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app/all-items-order` | `/dashboard/customize-app/all-items-order`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app` | `/dashboard/customize-app`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app/popular-items` | `/dashboard/customize-app/popular-items`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners/create` | `/dashboard/dashboard-banners/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners` | `/dashboard/dashboard-banners`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders` | `/dashboard/manage-orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/delivery-sequences` | `/dashboard/manage-orders/delivery-sequences`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/orders` | `/dashboard/manage-orders/orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/prices-overview` | `/dashboard/prices-overview`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-groupings/create` | `/dashboard/product-groupings/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-groupings` | `/dashboard/product-groupings`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/add` | `/dashboard/product-tags/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags` | `/dashboard/product-tags`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/order` | `/dashboard/product-tags/order`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/edit` | `/dashboard/product-tags/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/products/add` | `/dashboard/products/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/products/edit` | `/dashboard/products/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/products` | `/dashboard/products`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/rebalance-orders` | `/dashboard/rebalance-orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/send-notifications` | `/dashboard/send-notifications`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots/add` | `/dashboard/slots/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots` | `/dashboard/slots`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots/slot-details` | `/dashboard/slots/slot-details`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores/add` | `/dashboard/stores/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores/edit` | `/dashboard/stores/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores` | `/dashboard/stores`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/user-management` | `/dashboard/user-management`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/vendor-snippets` | `/dashboard/vendor-snippets`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons/edit/[id]` | `/dashboard/coupons/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners/edit/[id]` | `/dashboard/dashboard-banners/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/order-details/[id]` | `/dashboard/manage-orders/order-details/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/product-groupings/edit/[id]` | `/dashboard/product-groupings/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/products/detail/[id]` | `/dashboard/products/detail/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/slots/edit/[id]` | `/dashboard/slots/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/user-management/[id]` | `/dashboard/user-management/[id]`, params: Router.UnknownInputParams & { id: string | number; } }; + hrefOutputParams: { pathname: Router.RelativePathString, params?: Router.UnknownOutputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownOutputParams } | { pathname: `/`; params?: Router.UnknownOutputParams; } | { pathname: `/login`; params?: Router.UnknownOutputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard` | `/dashboard`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/complaints` | `/dashboard/complaints`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons/create` | `/dashboard/coupons/create`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons` | `/dashboard/coupons`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons/reserved-coupons` | `/dashboard/coupons/reserved-coupons`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app/all-items-order` | `/dashboard/customize-app/all-items-order`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app` | `/dashboard/customize-app`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app/popular-items` | `/dashboard/customize-app/popular-items`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners/create` | `/dashboard/dashboard-banners/create`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners` | `/dashboard/dashboard-banners`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders` | `/dashboard/manage-orders`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/delivery-sequences` | `/dashboard/manage-orders/delivery-sequences`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/orders` | `/dashboard/manage-orders/orders`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/prices-overview` | `/dashboard/prices-overview`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-groupings/create` | `/dashboard/product-groupings/create`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-groupings` | `/dashboard/product-groupings`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/add` | `/dashboard/product-tags/add`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags` | `/dashboard/product-tags`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/order` | `/dashboard/product-tags/order`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/edit` | `/dashboard/product-tags/edit`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/products/add` | `/dashboard/products/add`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/products/edit` | `/dashboard/products/edit`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/products` | `/dashboard/products`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/rebalance-orders` | `/dashboard/rebalance-orders`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/send-notifications` | `/dashboard/send-notifications`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots/add` | `/dashboard/slots/add`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots` | `/dashboard/slots`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots/slot-details` | `/dashboard/slots/slot-details`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores/add` | `/dashboard/stores/add`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores/edit` | `/dashboard/stores/edit`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores` | `/dashboard/stores`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/user-management` | `/dashboard/user-management`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/vendor-snippets` | `/dashboard/vendor-snippets`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons/edit/[id]` | `/dashboard/coupons/edit/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners/edit/[id]` | `/dashboard/dashboard-banners/edit/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/order-details/[id]` | `/dashboard/manage-orders/order-details/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/dashboard/product-groupings/edit/[id]` | `/dashboard/product-groupings/edit/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/dashboard/products/detail/[id]` | `/dashboard/products/detail/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/dashboard/slots/edit/[id]` | `/dashboard/slots/edit/[id]`, params: Router.UnknownOutputParams & { id: string; } } | { pathname: `${'/(drawer)'}/dashboard/user-management/[id]` | `/dashboard/user-management/[id]`, params: Router.UnknownOutputParams & { id: string; } }; + href: Router.RelativePathString | Router.ExternalPathString | `/${`?${string}` | `#${string}` | ''}` | `/login${`?${string}` | `#${string}` | ''}` | `/_sitemap${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard${`?${string}` | `#${string}` | ''}` | `/dashboard${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/complaints${`?${string}` | `#${string}` | ''}` | `/dashboard/complaints${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/coupons/create${`?${string}` | `#${string}` | ''}` | `/dashboard/coupons/create${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/coupons${`?${string}` | `#${string}` | ''}` | `/dashboard/coupons${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/coupons/reserved-coupons${`?${string}` | `#${string}` | ''}` | `/dashboard/coupons/reserved-coupons${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/customize-app/all-items-order${`?${string}` | `#${string}` | ''}` | `/dashboard/customize-app/all-items-order${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/customize-app${`?${string}` | `#${string}` | ''}` | `/dashboard/customize-app${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/customize-app/popular-items${`?${string}` | `#${string}` | ''}` | `/dashboard/customize-app/popular-items${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/dashboard-banners/create${`?${string}` | `#${string}` | ''}` | `/dashboard/dashboard-banners/create${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/dashboard-banners${`?${string}` | `#${string}` | ''}` | `/dashboard/dashboard-banners${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/manage-orders${`?${string}` | `#${string}` | ''}` | `/dashboard/manage-orders${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/manage-orders/delivery-sequences${`?${string}` | `#${string}` | ''}` | `/dashboard/manage-orders/delivery-sequences${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/manage-orders/orders${`?${string}` | `#${string}` | ''}` | `/dashboard/manage-orders/orders${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/prices-overview${`?${string}` | `#${string}` | ''}` | `/dashboard/prices-overview${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/product-groupings/create${`?${string}` | `#${string}` | ''}` | `/dashboard/product-groupings/create${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/product-groupings${`?${string}` | `#${string}` | ''}` | `/dashboard/product-groupings${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/product-tags/add${`?${string}` | `#${string}` | ''}` | `/dashboard/product-tags/add${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/product-tags${`?${string}` | `#${string}` | ''}` | `/dashboard/product-tags${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/product-tags/order${`?${string}` | `#${string}` | ''}` | `/dashboard/product-tags/order${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/product-tags/edit${`?${string}` | `#${string}` | ''}` | `/dashboard/product-tags/edit${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/products/add${`?${string}` | `#${string}` | ''}` | `/dashboard/products/add${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/products/edit${`?${string}` | `#${string}` | ''}` | `/dashboard/products/edit${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/products${`?${string}` | `#${string}` | ''}` | `/dashboard/products${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/rebalance-orders${`?${string}` | `#${string}` | ''}` | `/dashboard/rebalance-orders${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/send-notifications${`?${string}` | `#${string}` | ''}` | `/dashboard/send-notifications${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/slots/add${`?${string}` | `#${string}` | ''}` | `/dashboard/slots/add${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/slots${`?${string}` | `#${string}` | ''}` | `/dashboard/slots${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/slots/slot-details${`?${string}` | `#${string}` | ''}` | `/dashboard/slots/slot-details${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/stores/add${`?${string}` | `#${string}` | ''}` | `/dashboard/stores/add${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/stores/edit${`?${string}` | `#${string}` | ''}` | `/dashboard/stores/edit${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/stores${`?${string}` | `#${string}` | ''}` | `/dashboard/stores${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/user-management${`?${string}` | `#${string}` | ''}` | `/dashboard/user-management${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/vendor-snippets${`?${string}` | `#${string}` | ''}` | `/dashboard/vendor-snippets${`?${string}` | `#${string}` | ''}` | { pathname: Router.RelativePathString, params?: Router.UnknownInputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownInputParams } | { pathname: `/`; params?: Router.UnknownInputParams; } | { pathname: `/login`; params?: Router.UnknownInputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard` | `/dashboard`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/complaints` | `/dashboard/complaints`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons/create` | `/dashboard/coupons/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons` | `/dashboard/coupons`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/coupons/reserved-coupons` | `/dashboard/coupons/reserved-coupons`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app/all-items-order` | `/dashboard/customize-app/all-items-order`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app` | `/dashboard/customize-app`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/customize-app/popular-items` | `/dashboard/customize-app/popular-items`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners/create` | `/dashboard/dashboard-banners/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners` | `/dashboard/dashboard-banners`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders` | `/dashboard/manage-orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/delivery-sequences` | `/dashboard/manage-orders/delivery-sequences`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/orders` | `/dashboard/manage-orders/orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/prices-overview` | `/dashboard/prices-overview`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-groupings/create` | `/dashboard/product-groupings/create`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-groupings` | `/dashboard/product-groupings`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/add` | `/dashboard/product-tags/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags` | `/dashboard/product-tags`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/order` | `/dashboard/product-tags/order`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/product-tags/edit` | `/dashboard/product-tags/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/products/add` | `/dashboard/products/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/products/edit` | `/dashboard/products/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/products` | `/dashboard/products`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/rebalance-orders` | `/dashboard/rebalance-orders`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/send-notifications` | `/dashboard/send-notifications`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots/add` | `/dashboard/slots/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots` | `/dashboard/slots`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/slots/slot-details` | `/dashboard/slots/slot-details`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores/add` | `/dashboard/stores/add`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores/edit` | `/dashboard/stores/edit`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/stores` | `/dashboard/stores`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/user-management` | `/dashboard/user-management`; params?: Router.UnknownInputParams; } | { pathname: `${'/(drawer)'}/dashboard/vendor-snippets` | `/dashboard/vendor-snippets`; params?: Router.UnknownInputParams; } | `${'/(drawer)'}/dashboard/coupons/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/dashboard/coupons/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/dashboard-banners/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/dashboard/dashboard-banners/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/manage-orders/order-details/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/dashboard/manage-orders/order-details/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/product-groupings/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/dashboard/product-groupings/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/products/detail/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/dashboard/products/detail/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/slots/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/dashboard/slots/edit/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `${'/(drawer)'}/dashboard/user-management/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | `/dashboard/user-management/${Router.SingleRoutePart}${`?${string}` | `#${string}` | ''}` | { pathname: `${'/(drawer)'}/dashboard/coupons/edit/[id]` | `/dashboard/coupons/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/dashboard-banners/edit/[id]` | `/dashboard/dashboard-banners/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/manage-orders/order-details/[id]` | `/dashboard/manage-orders/order-details/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/product-groupings/edit/[id]` | `/dashboard/product-groupings/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/products/detail/[id]` | `/dashboard/products/detail/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/slots/edit/[id]` | `/dashboard/slots/edit/[id]`, params: Router.UnknownInputParams & { id: string | number; } } | { pathname: `${'/(drawer)'}/dashboard/user-management/[id]` | `/dashboard/user-management/[id]`, params: Router.UnknownInputParams & { id: string | number; } }; } } } diff --git a/apps/admin-ui/app/(drawer)/dashboard/products/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/products/index.tsx index 32f485b..7a281e1 100644 --- a/apps/admin-ui/app/(drawer)/dashboard/products/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/products/index.tsx @@ -1,9 +1,9 @@ import React, { useState, useMemo } from 'react'; -import { View, ScrollView, TouchableOpacity, RefreshControl } from 'react-native'; +import { View, TouchableOpacity, RefreshControl } from 'react-native'; import { Image } from 'expo-image'; import { useRouter } from 'expo-router'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; -import { AppContainer, MyText, tw, MyButton, useManualRefresh, SearchBar, useMarkDataFetchers } from 'common-ui'; +import { AppContainer, MyText, tw, MyButton, useManualRefresh, SearchBar, useMarkDataFetchers, MyFlatList } from 'common-ui'; import { trpc } from '@/src/trpc-client'; import type { AdminSku } from '@packages/shared'; @@ -98,46 +98,115 @@ export default function Products() { const inStockCount = products.filter(p => getDefaultSku(p) && !getDefaultSku(p)!.isOutOfStock).length; const outOfStockCount = products.filter(p => getDefaultSku(p)?.isOutOfStock).length; - + + const listHeader = ( + <> + {/* Header */} + + Products + router.push('/(drawer)/dashboard/products/add' as any)}> + Add Product + + + + {/* Search Bar */} + + {}} + placeholder="Search products..." + containerStyle={tw`mb-0`} + /> + + + {/* Filter Tabs */} + + + + + + + ); + + const renderItem = ({ item: product }: { item: any }) => { + const defaultSku = getDefaultSku(product) + const skuImages = defaultSku?.images ?? null + const isOut = defaultSku?.isOutOfStock ?? false + + return ( + + {/* Product Image */} + {skuImages && skuImages.length > 0 ? ( + + ) : ( + + + + )} + + {/* Product Info */} + + + + {product.name} + + + + + {isOut ? 'Out' : 'In'} + + + + + {product.shortDescription && ( + + {product.shortDescription} + + )} + + + + {product.skus?.length ?? 0} Variants + + + + {/* Action Buttons */} + + handleViewDetails(product.id)} + style={tw`flex-1 bg-gray-500 p-3 rounded-lg flex-row items-center justify-center`} + > + + View + + + handleEdit(product.id)} + style={tw`flex-1 bg-blue-500 p-3 rounded-lg flex-row items-center justify-center`} + > + + Edit + + + + + ) + }; + return ( - {/* Header */} - - Products - router.push('/(drawer)/dashboard/products/add' as any)}> - Add Product - - - - {/* Search Bar */} - - {}} - placeholder="Search products..." - containerStyle={tw`mb-0`} - /> - - - - {/* Filter Tabs */} - - - - - - - {/* Products List */} - - } - > - {filteredProducts.length === 0 ? ( + item.id.toString()} + ListHeaderComponent={listHeader} + ListEmptyComponent={ @@ -158,79 +227,14 @@ export default function Products() { )} - ) : ( - - {filteredProducts.map(product => { - const defaultSku = getDefaultSku(product) - const skuImages = defaultSku?.images ?? null - const isOut = defaultSku?.isOutOfStock ?? false - - return ( - - {/* Product Image */} - {skuImages && skuImages.length > 0 ? ( - - ) : ( - - - - )} - - {/* Product Info */} - - - - {product.name} - - - - - {isOut ? 'Out' : 'In'} - - - - - {product.shortDescription && ( - - {product.shortDescription} - - )} - - - - {product.skus?.length ?? 0} Variants - - - - {/* Action Buttons */} - - handleViewDetails(product.id)} - style={tw`flex-1 bg-gray-500 p-3 rounded-lg flex-row items-center justify-center`} - > - - View - - - handleEdit(product.id)} - style={tw`flex-1 bg-blue-500 p-3 rounded-lg flex-row items-center justify-center`} - > - - Edit - - - - - ) - })} - - )} - + } + contentContainerStyle={tw`pb-4`} + showsVerticalScrollIndicator={false} + refreshControl={ + + } + /> + ); -} \ No newline at end of file +} diff --git a/apps/user-ui/components/AddressSelector.tsx b/apps/user-ui/components/AddressSelector.tsx deleted file mode 100644 index 663beef..0000000 --- a/apps/user-ui/components/AddressSelector.tsx +++ /dev/null @@ -1,164 +0,0 @@ -import React from "react"; -import { View, Dimensions } from "react-native"; -import MaterialIcons from "@expo/vector-icons/MaterialIcons"; -import { - BottomDropdown, - MyTouchableOpacity, - MyText, - tw, - theme, -} from "common-ui"; -import { useAuth } from "@/src/contexts/AuthContext"; -import { trpc } from "@/src/trpc-client"; -import { useAddressStore } from "@/src/store/addressStore"; - -const { width: screenWidth } = Dimensions.get("window"); - -interface AddressSelectorProps { - mode?: "home"; - deliveryTime?: string; -} - -const AddressSelector: React.FC = ({ - mode = "home", - deliveryTime, -}) => { - const { isAuthenticated } = useAuth(); - const { selectedAddressId, setSelectedAddressId } = useAddressStore(); - - const { data: defaultAddressData } = - trpc.user.address.getDefaultAddress.useQuery(); - const { data: addressesData } = trpc.user.address.getUserAddresses.useQuery( - undefined, - { - enabled: isAuthenticated, - } - ); - - const defaultAddress = defaultAddressData?.data; - const addresses = addressesData?.data || []; - - // Transform addresses for dropdown - const addressOptions = addresses.map((address) => ({ - label: `${address.name} - ${address.addressLine1}, ${address.city}`, - value: address.id, - })); - - const handleAddressChange = ( - value: string | number | string[] | number[] - ) => { - const addressId = value as number; - setSelectedAddressId(addressId); - }; - - // Helper to get display parts - const getDisplayParts = (displayText?: string) => { - const fullText = - displayText || - (defaultAddress - ? `${defaultAddress.name} - ${defaultAddress.addressLine1}, ${defaultAddress.city}` - : ""); - let name = defaultAddress ? defaultAddress.name : "Home"; - let address = defaultAddress - ? `${defaultAddress.addressLine1}, ${defaultAddress.city}` - : "Add your delivery address"; - - if (fullText) { - const parts = fullText.split(" - "); - if (parts.length >= 1) name = parts[0]; - if (parts.length > 1) address = parts.slice(1).join(" - "); - } - return { name, address }; - }; - - const { name: defaultName, address: defaultAddr } = getDisplayParts(); - - if (!isAuthenticated) { - // Static display for non-authenticated users (Home mode) - return ( - - - - - - - - Delivery to {defaultName} - - - {defaultAddr} - - - - - ); - } - - return ( - { - const { name, address } = getDisplayParts(displayText); - - // Home styling - return ( - - - - - - - - - to {name} - - {/* */} - - - {address} - - - - - ); - }} - /> - ); -}; - -export default AddressSelector; diff --git a/apps/user-ui/components/CustomHeader.tsx b/apps/user-ui/components/CustomHeader.tsx deleted file mode 100644 index 1853bc7..0000000 --- a/apps/user-ui/components/CustomHeader.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from 'react'; -import { View } from 'react-native'; -import { useRouter } from 'expo-router'; -import { tw, theme, MyTouchableOpacity } from 'common-ui'; -import MaterialIcons from '@expo/vector-icons/MaterialIcons'; - -const CustomHeader = () => { - const router = useRouter(); - - return ( - - router.back()} - style={{ - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: theme.colors.gray2, - justifyContent: 'center', - alignItems: 'center', - }} - > - - - - router.push('/(drawer)/(tabs)/home/cart')} - style={{ - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: theme.colors.gray2, - justifyContent: 'center', - alignItems: 'center', - marginRight: 8, - }} - > - - - router.push('/(drawer)/(tabs)/me')} - style={{ - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: theme.colors.gray2, - justifyContent: 'center', - alignItems: 'center', - }} - > - - - - - ); -}; - -export default CustomHeader; \ No newline at end of file diff --git a/apps/user-ui/components/NextOrderGlimpse.tsx b/apps/user-ui/components/NextOrderGlimpse.tsx index 0e6f7f3..965e424 100644 --- a/apps/user-ui/components/NextOrderGlimpse.tsx +++ b/apps/user-ui/components/NextOrderGlimpse.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { View, TouchableOpacity, ActivityIndicator, Linking } from 'react-native'; +import React, { useState, useCallback, useRef } from 'react'; +import { View, TouchableOpacity, ActivityIndicator, Linking, ScrollView, Dimensions, NativeSyntheticEvent, NativeScrollEvent } from 'react-native'; import { useRouter } from 'expo-router'; import { tw, MyText } from 'common-ui'; import { useNavigationTarget } from 'common-ui/hooks/useNavigationTarget'; @@ -11,6 +11,10 @@ import { orderStatusManipulator } from '@/src/lib/string-manipulators'; import { useGetEssentialConsts } from '@/src/hooks/prominent-api-hooks'; import { useUserDetails } from '@/src/contexts/AuthContext'; +const { width: screenWidth } = Dimensions.get('window'); +const CARD_WIDTH = (screenWidth - 48) * 0.95; // card width (24px padding each side), reduced 5% +const SNAP_INTERVAL = CARD_WIDTH + 24; // card + right margin = page width + interface OrderItem { productName: string; quantity: number; @@ -40,10 +44,115 @@ interface Order { createdAt: string; } +interface OrderCardProps { + order: Order; + onPress: () => void; + supportMobile?: string | null; +} + +function OrderCard({ order, onPress, supportMobile }: OrderCardProps) { + return ( + + + + + + Upcoming Order + + {order.isFlashDelivery && ( + + + FLASH + + )} + + + + + #{order.orderId} + + {order.items.length} {order.items.length === 1 ? 'item' : 'items'} • ₹{order.totalAmount} + + + + {orderStatusManipulator(order.deliveryStatus)} + + + + + + + {order.isFlashDelivery + ? "30-Min Delivery" + : (() => { + const startTime = dayjs(order.deliveryDate); + const endTime = startTime.add(1, 'hour'); + return `${startTime.format("DD MMM, hh:mm A")} - ${endTime.format("hh:mm A")}`; + })() + } + + + + {order.items.length > 0 && ( + + + {order.items.slice(0, 3).map((item, idx) => ( + 0 ? -8 : 0 } + ]} + > + + + ))} + {order.items.length > 3 && ( + + +{order.items.length - 3} + + )} + + Track Order + + + )} + + {/* Support Mobile Number */} + {supportMobile && ( + Linking.openURL(`tel:${supportMobile}`)} + > + + + Need help? Call {supportMobile} + + + )} + + + ); +} + export default function NextOrderGlimpse() { const router = useRouter(); const { setNavigationTarget } = useNavigationTarget(); const userDetails = useUserDetails(); + const [currentIndex, setCurrentIndex] = useState(0); + const scrollViewRef = useRef(null); const { data: ordersData, isLoading: ordersLoading } = trpc.user.order.getOrders.useQuery({ page: 1, @@ -78,7 +187,15 @@ export default function NextOrderGlimpse() { return 0; }); - const nextOrder = upcomingOrders[0] || null; + const handleScroll = useCallback((event: NativeSyntheticEvent) => { + const index = Math.round(event.nativeEvent.contentOffset.x / SNAP_INTERVAL); + setCurrentIndex(Math.min(Math.max(index, 0), upcomingOrders.length - 1)); + }, [upcomingOrders.length]); + + const handleOrderPress = useCallback((order: Order) => { + setNavigationTarget(`/(drawer)/(tabs)/me/my-orders/${order.id}`); + router.replace('/(drawer)/(tabs)/me'); + }, [router, setNavigationTarget]); if (!userDetails) { return null; @@ -94,104 +211,44 @@ export default function NextOrderGlimpse() { ); } - if (!nextOrder) { + if (upcomingOrders.length === 0) { return null; } return ( - { - setNavigationTarget(`/(drawer)/(tabs)/me/my-orders/${nextOrder.id}`); - router.replace('/(drawer)/(tabs)/me'); - }} - > - - - - - Upcoming Order - - {nextOrder.isFlashDelivery && ( - - - FLASH - - )} - - - - - #{nextOrder.orderId} - - {nextOrder.items.length} {nextOrder.items.length === 1 ? 'item' : 'items'} • ₹{nextOrder.totalAmount} - - - - {orderStatusManipulator(nextOrder.deliveryStatus)} - - - - - + + {upcomingOrders.map((order) => ( + handleOrderPress(order)} + supportMobile={essentialConsts?.supportMobile} /> - - {nextOrder.isFlashDelivery - ? "30-Min Delivery" - : (() => { - const startTime = dayjs(nextOrder.deliveryDate); - const endTime = startTime.add(1, 'hour'); - return `${startTime.format("DD MMM, hh:mm A")} - ${endTime.format("hh:mm A")}`; - })() - } - + ))} + + + {/* Pagination Dots */} + {upcomingOrders.length > 1 && ( + + {upcomingOrders.map((_, index) => ( + + ))} - - {nextOrder.items.length > 0 && ( - - - {nextOrder.items.slice(0, 3).map((item, idx) => ( - 0 ? -8 : 0 } - ]} - > - - - ))} - {nextOrder.items.length > 3 && ( - - +{nextOrder.items.length - 3} - - )} - - Track Order - - - )} - - {/* Support Mobile Number */} - {essentialConsts?.supportMobile && ( - Linking.openURL(`tel:${essentialConsts.supportMobile}`)} - > - - - Need help? Call {essentialConsts.supportMobile} - - - )} - - + )} + ); } diff --git a/apps/user-ui/components/ProductDetail.tsx b/apps/user-ui/components/ProductDetail.tsx index 9f4d6a1..2709a08 100644 --- a/apps/user-ui/components/ProductDetail.tsx +++ b/apps/user-ui/components/ProductDetail.tsx @@ -228,7 +228,6 @@ const ProductDetail: React.FC = ({ productId, isFlashDeliver return ( - {/* */} { - const router = useRouter(); - const isDevMode = useIsDevMode(); - const { data, isLoading } = trpc.user.user.checkProfileComplete.useQuery(); - const [dialogOpen, setDialogOpen] = React.useState(false); - - React.useEffect(() => { - if (!isLoading && data && !data.isComplete) { - setDialogOpen(true); - } - }, [data, isLoading]); - - if (isLoading || isDevMode) return null; - - return ( - setDialogOpen(false)}> - - - Complete Your Profile - - - Please complete your profile for a better experience. - - - setDialogOpen(false)} - fillColor="gray1" - textColor="black1" - /> - { setDialogOpen(false); router.push('/(drawer)/(tabs)/me/edit-profile'); }} - fillColor="brand500" - textColor="white1" - /> - - - - ); -}; - -export default ProfileChecker; \ No newline at end of file diff --git a/apps/user-ui/components/UserAddressHeader.tsx b/apps/user-ui/components/UserAddressHeader.tsx deleted file mode 100644 index c3f52a2..0000000 --- a/apps/user-ui/components/UserAddressHeader.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import { View } from 'react-native'; -import { useRouter } from 'expo-router'; -import MaterialIcons from '@expo/vector-icons/MaterialIcons'; -import { trpc } from '@/src/trpc-client'; -import { tw, MyText, MyTouchableOpacity } from 'common-ui'; - -export default function UserAddressHeader() { - const router = useRouter(); - const { data: defaultAddressResponse } = trpc.user.address.getDefaultAddress.useQuery(); - const defaultAddress = defaultAddressResponse?.data; - - // Use a cleaner, white aesthetic that doesn't dominate the eye but feels premium - return ( - - - router.push('/(drawer)/(tabs)/me/addresses')} - style={tw`flex-1`} - > - - {/* Small subtle brand indicator */} - - - - Delivering to - - - {defaultAddress?.name ? defaultAddress.name.split(' ')[0] : 'Home'} - - - - - - {defaultAddress ? `${defaultAddress.addressLine1}, ${defaultAddress.city}` : 'Add a delivery address'} - - - - - ); -} \ No newline at end of file diff --git a/apps/user-ui/components/icons/OrderAgainIcon.tsx b/apps/user-ui/components/icons/OrderAgainIcon.tsx deleted file mode 100644 index 8f2e3fb..0000000 --- a/apps/user-ui/components/icons/OrderAgainIcon.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import Svg, { Path } from 'react-native-svg'; - -interface OrderAgainIconProps { - focused: boolean; - size: number; - color: string; -} - -const OrderAgainIcon: React.FC = ({ focused, size, color }) => { - const iconColor = focused ? '#2563EB' : '#2D264B'; // Use focused color when focused, original color when not - - return ( - - - - - ); -}; - -export default OrderAgainIcon; \ No newline at end of file diff --git a/apps/user-ui/components/ui/IconSymbol.ios.tsx b/apps/user-ui/components/ui/IconSymbol.ios.tsx deleted file mode 100755 index 9177f4d..0000000 --- a/apps/user-ui/components/ui/IconSymbol.ios.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols'; -import { StyleProp, ViewStyle } from 'react-native'; - -export function IconSymbol({ - name, - size = 24, - color, - style, - weight = 'regular', -}: { - name: SymbolViewProps['name']; - size?: number; - color: string; - style?: StyleProp; - weight?: SymbolWeight; -}) { - return ( - - ); -} diff --git a/apps/user-ui/components/ui/IconSymbol.tsx b/apps/user-ui/components/ui/IconSymbol.tsx deleted file mode 100755 index b7ece6b..0000000 --- a/apps/user-ui/components/ui/IconSymbol.tsx +++ /dev/null @@ -1,41 +0,0 @@ -// Fallback for using MaterialIcons on Android and web. - -import MaterialIcons from '@expo/vector-icons/MaterialIcons'; -import { SymbolWeight, SymbolViewProps } from 'expo-symbols'; -import { ComponentProps } from 'react'; -import { OpaqueColorValue, type StyleProp, type TextStyle } from 'react-native'; - -type IconMapping = Record['name']>; -type IconSymbolName = keyof typeof MAPPING; - -/** - * Add your SF Symbols to Material Icons mappings here. - * - see Material Icons in the [Icons Directory](https://icons.expo.fyi). - * - see SF Symbols in the [SF Symbols](https://developer.apple.com/sf-symbols/) app. - */ -const MAPPING = { - 'house.fill': 'home', - 'paperplane.fill': 'send', - 'chevron.left.forwardslash.chevron.right': 'code', - 'chevron.right': 'chevron-right', -} as IconMapping; - -/** - * An icon component that uses native SF Symbols on iOS, and Material Icons on Android and web. - * This ensures a consistent look across platforms, and optimal resource usage. - * Icon `name`s are based on SF Symbols and require manual mapping to Material Icons. - */ -export function IconSymbol({ - name, - size = 24, - color, - style, -}: { - name: IconSymbolName; - size?: number; - color: string | OpaqueColorValue; - style?: StyleProp; - weight?: SymbolWeight; -}) { - return ; -} diff --git a/apps/user-ui/components/ui/TabBarBackground.ios.tsx b/apps/user-ui/components/ui/TabBarBackground.ios.tsx deleted file mode 100755 index 495b2d4..0000000 --- a/apps/user-ui/components/ui/TabBarBackground.ios.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs'; -import { BlurView } from 'expo-blur'; -import { StyleSheet } from 'react-native'; - -export default function BlurTabBarBackground() { - return ( - - ); -} - -export function useBottomTabOverflow() { - return useBottomTabBarHeight(); -} diff --git a/apps/user-ui/components/ui/TabBarBackground.tsx b/apps/user-ui/components/ui/TabBarBackground.tsx deleted file mode 100755 index 70d1c3c..0000000 --- a/apps/user-ui/components/ui/TabBarBackground.tsx +++ /dev/null @@ -1,6 +0,0 @@ -// This is a shim for web and Android where the tab bar is generally opaque. -export default undefined; - -export function useBottomTabOverflow() { - return 0; -} diff --git a/apps/user-ui/hooks/useCurrentUserId.ts b/apps/user-ui/hooks/useCurrentUserId.ts deleted file mode 100755 index 7f92190..0000000 --- a/apps/user-ui/hooks/useCurrentUserId.ts +++ /dev/null @@ -1,13 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { getCurrentUserId } from '@/utils/getCurrentUserId'; - -export function useCurrentUserId(): {userId:number|null, refetchUserId: () => void} { - const [userId, setUserId] = useState(null); - const refetchUserId = React.useCallback(() => { - getCurrentUserId().then(setUserId); - },[]) - useEffect(() => { - getCurrentUserId().then(setUserId); - }, []); - return {userId,refetchUserId}; -} diff --git a/apps/user-ui/hooks/useHideDrawerHeader.ts b/apps/user-ui/hooks/useHideDrawerHeader.ts deleted file mode 100755 index c277ec2..0000000 --- a/apps/user-ui/hooks/useHideDrawerHeader.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useFocusEffect, useNavigation } from "expo-router"; -import React from "react"; - - -function useHideDrawerHeader() { - - const navigation = useNavigation(); - useFocusEffect(() => { - let drawerNav = navigation.getParent(); - const drawerNavList:any = []; - // Collect all parent navigators - while (drawerNav) { - drawerNavList.push(drawerNav); - drawerNav = drawerNav.getParent(); - } - - drawerNavList.at(-3)?.setOptions({ headerShown: false }); - - return () => { - drawerNavList.at(-3)?.setOptions({ headerShown: true }); - }; - }); - return null; -} - -export default useHideDrawerHeader; diff --git a/apps/user-ui/hooks/usePhonepeSdk.ts b/apps/user-ui/hooks/usePhonepeSdk.ts deleted file mode 100755 index 2ec5276..0000000 --- a/apps/user-ui/hooks/usePhonepeSdk.ts +++ /dev/null @@ -1,34 +0,0 @@ - -import { useEffect } from 'react'; -import PhonePePaymentSDK from 'react-native-phonepe-pg'; - -export function usePhonepeSdk() { - // const { data: creds, isLoading, isError } = usePhonepeCreds(); - const creds: any = {}; - const isError = false; - const isLoading = false; - - useEffect(() => { - if (creds && creds.clientId && creds.clientVersion) { - PhonePePaymentSDK.init('SANDBOX', creds.clientId, creds.clientId, true); - } - }, [creds]); - - const startTransaction = async (orderId: string, token: string) => { - try { - const request = { - orderId, - token, - merchantId: creds?.merchantId, - paymentMode: { type: 'PAY_PAGE' } - }; - const stringReq = JSON.stringify(request); - const response = await PhonePePaymentSDK.startTransaction(stringReq, null); - return response; - } catch (error) { - throw error; - } - }; - - return { startTransaction, isLoading, isError, creds }; -} diff --git a/apps/user-ui/hooks/useThemeColor.ts b/apps/user-ui/hooks/useThemeColor.ts deleted file mode 100755 index 0608e73..0000000 --- a/apps/user-ui/hooks/useThemeColor.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Learn more about light and dark modes: - * https://docs.expo.dev/guides/color-schemes/ - */ - -import { Colors } from '@/constants/Colors'; -import { useColorScheme } from '@/hooks/useColorScheme'; - -export function useThemeColor( - props: { light?: string; dark?: string }, - colorName: keyof typeof Colors.light & keyof typeof Colors.dark -) { - const theme = useColorScheme() ?? 'light'; - const colorFromProps = props[theme]; - - if (colorFromProps) { - return colorFromProps; - } else { - return Colors[theme][colorName]; - } -} diff --git a/apps/user-ui/services/axios-user-ui.ts b/apps/user-ui/services/axios-user-ui.ts deleted file mode 100644 index 9b36cc7..0000000 --- a/apps/user-ui/services/axios-user-ui.ts +++ /dev/null @@ -1,61 +0,0 @@ -import axiosParent from 'axios'; -import { FORCE_LOGOUT_EVENT } from 'common-ui/src/lib/const-strs'; -import { DeviceEventEmitter } from 'react-native' -// import { getJWT } from '@/hooks/useJWT'; -import { BASE_API_URL } from 'common-ui'; -import { getAuthToken } from '@/hooks/useJWT'; - -// export const API_BASE_URL = 'http://192.168.100.95:4000'; // Change to your API base URL -// const API_BASE_URL = 'https://www.technocracy.ovh/mf'; // Change to your API base URL -// const API_BASE_URL = 'http://10.195.26.42:4000'; // Change to your API base URL -// const API_BASE_URL = 'http://localhost:4000/api/mobile/'; // Change to your API base URL -// const API_BASE_URL = 'https://car-safar.com/api/mobile/'; // Change to your API base URL - -const axios = axiosParent.create({ - baseURL: BASE_API_URL + '/api/v1', - timeout: 60000, - // headers: { - // 'Content-Type': 'application/json', - // }, -}); - - -axios.interceptors.request.use( - async (config) => { - // const token = await getJWT(); - const token = await getAuthToken(); - - if (token) { - config.headers = config.headers || {}; - config.headers['Authorization'] = `Bearer ${token}`; - } - return config; - }, - (error) => Promise.reject(error) -); - -axios.interceptors.response.use( - (response) => response, - (error) => { - - const status = error?.status; - const msg = error.response?.data?.error; - - if (status === 401 && msg.startsWith('Access denied')) { - // Handle unauthorized access - DeviceEventEmitter.emit(FORCE_LOGOUT_EVENT); - } - const message = error?.response?.data?.error; - - if (msg) { - // Optionally, you can attach the message to the error object or throw a new error - const err = new Error(msg); - // Optionally attach the original error for debugging - (err as any).original = error; - return Promise.reject(err); - } - return Promise.reject(error); - } -); - -export default axios; diff --git a/docs/common-ui-dependency-audit.md b/docs/common-ui-dependency-audit.md new file mode 100644 index 0000000..0e6c5e4 --- /dev/null +++ b/docs/common-ui-dependency-audit.md @@ -0,0 +1,55 @@ +# Dependency Audit — packages/ui (common-ui) + +Audited 2026-08-16. Packages listed below are declared in `package.json` but **never imported** anywhere in this package's own source (`src/`, `hooks/`, `index.ts`). + +## Never used in this package + +- `@react-native-google-signin/google-signin` +- `@react-native-picker/picker` +- `@react-navigation/bottom-tabs` +- `@react-navigation/drawer` +- `@react-navigation/elements` +- `buffer` +- `dayjs` +- `expo` +- `expo-blur` +- `expo-dev-client` +- `expo-device` +- `expo-font` +- `expo-haptics` +- `expo-linear-gradient` +- `expo-linking` +- `expo-notifications` +- `expo-router` +- `expo-splash-screen` +- `expo-symbols` +- `expo-system-ui` +- `formik` +- `jwt-decode` +- `react-dom` +- `react-hook-form` +- `react-native-gesture-handler` +- `react-native-pager-view` +- `react-native-phonepe-pg` +- `react-native-razorpay` +- `react-native-reanimated` +- `react-native-safe-area-context` +- `react-native-screens` +- `react-native-tab-view` +- `react-native-toast-message` +- `react-native-web` +- `react-native-webview` +- `yup` + +## Caveats + +- Several of the above (`react-native-gesture-handler`, `react-native-reanimated`, `react-native-safe-area-context`, `react-native-screens`, `react-navigation/*`, `expo-router`, etc.) are runtime peer/transitive requirements of `@react-navigation/native` and the consuming Expo apps, which declare them in their own `package.json`. They are unused in `packages/ui` but not removable from the workspace if the apps rely on hoisting. +- `expo` (base) is not imported directly but is required by the `expo-*` modules that are used. +- Safest candidates for removal (not used by apps either): `expo-dev-client`, `react-native-phonepe-pg`. + +## Imported but not declared (opposite problem) + +The package imports these without listing them in `package.json`; they currently resolve via hoisting: + +- `expo-auth-session` +- `react-native-svg` diff --git a/docs/user-ui-cart-management.md b/docs/user-ui-cart-management.md new file mode 100644 index 0000000..7e59f26 --- /dev/null +++ b/docs/user-ui-cart-management.md @@ -0,0 +1,182 @@ +# Cart Management in `apps/user-ui` — Detailed Documentation + +> How the customer cart works end-to-end: local storage, React Query hooks, the two cart types (regular + flash), pricing, slots, coupons, checkout handoff, and all edge cases. + +--- + +## 1. Architecture Overview + +The cart is **100% client-side / local-first**. There is **no server cart** — items live in local storage (SecureStore on native, localStorage on web via `StorageServiceCasual`), and are resolved against the cached product catalog + slot/availability data on the device. + +``` +AddToCartDialog / ProductCard / FloatingCartBar + │ useCartStore.setAddedToCartProduct() (trigger dialog) + ▼ +useAddToCart / useUpdateCartItem / useRemoveFromCart (cart-query-hooks.tsx) + │ mutations write to local storage + ▼ +StorageServiceCasual (key: "cart_items" | "flash_cart_items") + ▲ +useGetCart() (query reads local storage + merges product/availability data) + │ +cart-page.tsx / floating-cart-bar.tsx / checkout-page.tsx +``` + +### Key files +| File | Role | +|---|---| +| `hooks/cart-query-hooks.tsx` | The core: local-storage CRUD + React Query hooks (`useGetCart`, `useAddToCart`, `useUpdateCartItem`, `useRemoveFromCart`, `clearLocalCart`). | +| `src/store/cartStore.ts` | Zustand: `addedToCartProduct` — which product opened the AddToCart dialog. | +| `src/store/flashCartStore.ts` | Zustand: `addedFlashProduct` — which product was routed to the flash flow. | +| `src/store/centralProductStore.ts` | Zustand: cached products + `productsById` map (from `useAllProducts`). | +| `src/store/centralSlotStore.ts` | Zustand: slots + `productSlotsMap` (per-product availability/out-of-stock/flash). | +| `components/cart-page.tsx` | The full cart screen (regular + flash via prop). | +| `components/floating-cart-bar.tsx` | Collapsible cart summary bar (count, total, free-delivery progress). | +| `src/components/AddToCartDialog.tsx` | Slot/quantity/flash chooser when adding/updating an item. | +| `components/checkout-page.tsx` | Reads cart via URL params (`slots=`, `coupons=`, `deliveryPrice=`) — the cart is passed by **reference**, not re-read. | + +--- + +## 2. Data Model + +### Local storage item (`LocalCartItem`) +```ts +{ + id: number, // local incrementing id (max existing id + 1) + skuId: number, // the product/SKU id + quantity: number, + slotId: number, // delivery slot id; 0 = flash/unspecified + addedAt: string, // ISO timestamp +} +``` +Stored under `cart_items` (regular) or `flash_cart_items` (flash) via `StorageServiceCasual` (SecureStore native / localStorage web). + +### Computed cart (`CartData`) +```ts +{ + items: CartItem[], + totalItems: number, // item count (not quantity) + totalAmount: number, // Σ(price × quantity) +} +``` +`CartItem` = local item + `subtotal` (computed from `productBasic.price`). + +### Product resolution +`useGetCart` builds `items` by looking up each `skuId` in `productsById` (central product store) **and** requiring `productSlotsMap[skuId]` to exist — **if either is missing, the item is silently dropped** from the cart view (not deleted from storage). + +--- + +## 3. Flow: Add to Cart + +1. **Trigger**: `ProductCard` / home / store / search call `useCartStore.setAddedToCartProduct({ productId, product })` → the `AddToCartDialog` opens (regular) OR `useFlashCartStore.setAddedFlashProduct` (flash). +2. **Dialog** (`AddToCartDialog.tsx`): + - Lists **available slots** for the product (from `useSlots()` → `productSlotIdsMap`, filtered to future `freezeTime`). + - Shows **"1 hr Delivery"** option if `productSlotsMap[id].isFlashAvailable` AND flash is enabled. + - Quantity via `Quantifier` (step 1 — not the product's `incrementStep`!). + - **Pre-fills** from existing cart item: if the product is already in the cart, it loads the existing quantity + slotId. + - "Add to Cart" / "Update Item" (if already in cart) / "Remove" (if updating). +3. **Mutation** (`useAddToCart` / `useUpdateCartItem`): + - `addToLocalCart`: if `skuId` exists → **merge quantity** (add to existing) + optionally update slotId; else push new item. + - Requires `slotId` (throws if null). + - `updateLocalCartItem`: set `quantity` on the item (by local `id`). + - `removeFromLocalCart`: filter out by local `id`. +4. **Flash special-case**: choosing "1 hr Delivery" sets `useFlashCartStore.setAddedFlashProduct(...)` and navigates to the flash products page — it does **NOT** add to the regular cart via the dialog; the flash cart is a separate local list. + +--- + +## 4. Flow: Cart Page + +`cart-page.tsx` (`isFlashDelivery` prop selects `cartType`): +- **Loading**: blocks on `useGetCart` loading + (regular only) `getCartSlots` loading. +- **Per-item**: + - Image, name, unit, `Quantifier` (step = product `incrementStep`). + - Quantity to **0** → confirmation alert → remove. + - **Slot selection** (regular only): `BottomDropdown` from `trpc.user.cart.getCartSlots({ productIds })`, filtered to future slots. Flash forces `slotId = 0`. + - Price: regular uses `product.price`; flash uses `product.flashPrice ?? product.price`. + - **Availability** logic per item: + - `productSlotInfo.isOutOfStock` → unavailable "Out of Stock". + - Flash: not flash-eligible → "Not available for flash delivery. Please remove". + - Regular: no slots → "No delivery slots available". +- **Auto-slot effect**: on `slotsData`/`cartItems` change, auto-selects each item's slot (keeps existing if still valid, else first upcoming; flash = 0). +- **Coupons**: `trpc.user.coupon.getEligible` → eligible list; min-order + usage-limit filtering client-side; discount = percent (capped at `maxValue`) or flat (capped at total); applied coupon id passed to checkout via URL. +- **Bill**: Item Total → Product Discount → Coupon Applied → Delivery Fee (0 if `finalTotal >= threshold`) → To Pay. Free-delivery nudge + "You saved ₹X" banner. +- **Checkout handoff**: builds `slots=:;...` + `coupons=` + `deliveryPrice=` URL params → navigates to `/home/checkout` or `/flash-delivery/checkout`. +- **Guard**: if no available items → alert (all OOS / none flash-eligible / missing slots) and blocks checkout. + +--- + +## 5. Flow: Floating Cart Bar + +- Reads `useGetCart` for the active cart type; shows count + `totalCartValue` + free-delivery progress (regular vs flash thresholds). +- **Expanded dialog**: list with `MiniQuantifier` (0 = remove), per-item slot dropdown (regular), subtotal, "Go to cart" → cart page. +- **Slot-reassignment effect** (runs once on mount): for regular items whose `slotId` is no longer in `productSlotsMap[skuId].slots`, it **removes + re-adds** the item with the nearest slot (`removeFromCart.mutate` + `addToCartHook.addToCart`). (Note: `addToCart(item.skuId, item.quantity, nearestSlotId)` — passing `quantity` as the *quantity* arg.) + +--- + +## 6. Checkout integration + +- Checkout does **not** re-read local storage directly — it receives the cart items **by URL params** (`slots=`, `coupons=`, `deliveryPrice=`) from the cart page. +- This means the checkout's item set/quantities/slots are **frozen at navigation time**; if the cart changes after, checkout uses the snapshot. + +--- + +## 7. Edge Cases & Observations + +### Data / storage +1. **Missing product or slot data → item dropped from view** (`useGetCart` returns `null` for items lacking `productBasic` or `productAvailability`). The item stays in storage but is invisible — potential "phantom cart" if product is later removed from catalog. +2. **Duplicate add merges quantity** (same `skuId` → `quantity +=`). No separate line items. +3. **`slotId: 0` sentinel** for flash — 0 is not a real slot; code must treat 0 as "flash/unspecified". +4. **Local `id` generation** = `max(existing ids) + 1`. Deleting the highest-id item then adding reuses ids (fine) — but concurrent adds (two rapid taps) could race since id is computed from the read-then-write sequence (no lock). +5. **Storage failures** (`StorageServiceCasual.setItem` error) are caught by the service and return false — the mutation still resolves, but the write may not have persisted (silent data loss risk). + +### Slot / availability +6. **Auto-slot reassignment**: if a cart item's saved slot becomes invalid, the cart page picks the first upcoming slot silently; the floating bar instead does remove+re-add. Two different behaviors for the same situation. +7. **Slot changes in cart page are local-only** (`selectedSlots` state) — they're NOT written back to `LocalCartItem.slotId` until checkout builds the URL. (The `useEffect` reads `cartData` slotId but the dropdown only updates `selectedSlots`.) → **If the user leaves the cart without checking out, the new slot choice is lost.** +8. **`AddToCartDialog` requires a slot** — if a product has no future slots, the dialog can't add it (button disabled). Good, but the flash path can bypass via "1 hr Delivery". +9. **Flash eligibility** is from `productSlotsMap[id].isFlashAvailable` — but the flash cart page also checks `flashEligibleProductIds` (derived from `products` + `productSlotsMap`). Two sources that should agree. +10. **Out-of-stock mid-cart**: if a product becomes OOS after adding, cart page shows "Out of Stock" and excludes it from totals/checkout, but does NOT auto-remove it. + +### Quantity / pricing +11. **Dialog step = 1** vs **cart page step = product.incrementStep** — inconsistent stepping between the two add/update UIs. (A product with 500g increment could be set to any integer in the dialog.) +12. **`baseTotalPrice` (coupon eligibility) uses `product.price`** (not flash price) even in flash cart — coupon min-order check may be wrong for flash. +13. **`totalPrice` filters OOS items** — good — but the `Quantifier` still shows them; quantity edits on OOS items are allowed. +14. **Flash pricing**: `flashPrice ?? price` — if `flashPrice` is `0` or `null`, falls back to base price; if `flashPrice` is a valid string, used. (Floating bar + cart page consistent.) +15. **Discount cap for flat coupons**: `Math.min(flatDiscount, maxValue || totalPrice)` — reasonable; percent capped at `maxValue || Infinity`. + +### Coupons +16. **Usage-limit coupons are filtered out entirely** from the dropdown (`.filter(coupon => coupon.ineligibilityReason !== "Usage limit exceeded")`) — a used-up coupon disappears rather than showing "used up". +17. **Min-order coupons show disabled** with reason — good. +18. **Selected coupon is only applied to available items' total** — matches backend intent (coupon applies to non-OOS items). +19. **Coupon passed by id to checkout** — checkout re-validates on the backend; client discount is a preview. + +### Checkout / navigation +20. **Cart is snapshotted into URL params** — long carts → long URLs; quantities/slots frozen at navigation. +21. **`availableItems.length === 0` guard** produces specific alerts (all OOS / none flash-eligible / missing slots) — good UX. +22. **Partial availability**: if only some items are available, checkout proceeds with only the available ones — the unavailable ones stay in the cart (not removed). +23. **Cart type switcher** navigates between regular/flash flows, but does NOT move items — each cart type is independent. + +### Flash-specific +24. **Flash cart items have `slotId: 0`** — the cart page forces `selectedSlots[item.id] = 0` for flash. +25. **Adding via "1 hr Delivery" in the dialog does NOT add to the regular cart** — it sets `addedFlashProduct` and navigates to flash products; the actual add happens on the flash page. (If the user abandons the flash page, nothing was added.) +26. **`isFlashDeliveryEnabled` gate** — flash option only shows if the const is true. + +### Concurrency / timing +27. **`useGetCart` enabled only when `productsById` is populated** — before the central product store loads, the cart query is disabled (no stale empty cart flash). Good. +28. **`refetchOnWindowFocus`** default true → returning to the app refreshes cart totals (from local storage) but prices come from cached products — price updates in the catalog reflect on next product refetch. +29. **Floating bar slot-reassignment runs once (`[]` deps)** — on mount only; slot validity isn't re-checked on later slot-data changes. +30. **Remove-then-add in floating bar** for invalid slots changes the local item `id` (new id) — any UI holding the old id could mismatch. + +--- + +## 8. Potential improvements (suggestions, not required) + +- **Persist slot changes**: write `selectedSlots` back to `LocalCartItem.slotId` so slot choices survive leaving the cart. +- **Unify quantity step** (dialog step=1 vs cart incrementStep). +- **Fix flash coupon min-order** to use flash price. +- **Handle "phantom items"**: purge local cart entries whose product no longer exists (or show them as unavailable). +- **Serialize add-to-cart writes** (mutex/queue) to avoid id races on rapid taps. +- **Surface storage write failures** instead of silently succeeding. + +--- + +*Documentation based on code reading of `cart-query-hooks.tsx`, `cartStore.ts`, `flashCartStore.ts`, `centralProductStore.ts`, `centralSlotStore.ts`, `cart-page.tsx`, `floating-cart-bar.tsx`, `AddToCartDialog.tsx`, and `checkout-page.tsx`.* diff --git a/packages/ui/hooks/useIsDevMode.ts b/packages/ui/hooks/useIsDevMode.ts deleted file mode 100644 index f301e4b..0000000 --- a/packages/ui/hooks/useIsDevMode.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useMemo } from 'react'; -import Constants from 'expo-constants'; - -export const useIsDevMode = () => { - return useMemo(() => { - return !Constants.isDevice; - }, []); -}; \ No newline at end of file diff --git a/packages/ui/hooks/usePagination.tsx b/packages/ui/hooks/usePagination.tsx deleted file mode 100644 index 533b2f1..0000000 --- a/packages/ui/hooks/usePagination.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { useState } from 'react'; -import { TouchableOpacity, Text, View } from 'react-native'; -import { tw } from '../index'; - -export const usePagination = (initialPageSize: number = 10) => { - const [currentPage, setCurrentPage] = useState(1); - const pageSize = initialPageSize; - - const PaginationComponent = ({ totalCount }: { totalCount: number }) => { - const totalPages = Math.ceil(totalCount / pageSize); - - if (totalCount === 0 || totalPages <= 1) { - return null; - } - - const getVisiblePages = () => { - const pages: (number | string)[] = []; - const maxVisible = 3; - const half = Math.floor(maxVisible / 2); - - let start = Math.max(1, currentPage - half); - let end = Math.min(totalPages, start + maxVisible - 1); - - if (end - start + 1 < maxVisible) { - start = Math.max(1, end - maxVisible + 1); - } - - if (start > 1) { - pages.push(1); - if (start > 2) pages.push('...'); - } - - for (let i = start; i <= end; i++) { - pages.push(i); - } - - if (end < totalPages) { - if (end < totalPages - 1) pages.push('...'); - pages.push(totalPages); - } - - return pages; - }; - - const visiblePages = getVisiblePages(); - - return ( - - - setCurrentPage(currentPage - 1)} - style={tw`px-4 py-2 rounded-lg ${currentPage === 1 ? 'bg-gray-100' : 'bg-blue-500'}`} - > - - Previous - - - - - {visiblePages.map((page, index) => ( - typeof page === 'number' && setCurrentPage(page)} - style={tw`px-3 py-2 mx-1 rounded-lg ${ - typeof page === 'number' && currentPage === page ? 'bg-blue-500' : 'bg-gray-100' - }`} - > - - {page} - - - ))} - - - setCurrentPage(currentPage + 1)} - style={tw`px-4 py-2 rounded-lg ${currentPage === totalPages ? 'bg-gray-100' : 'bg-blue-500'}`} - > - - Next - - - - - ); - }; - - return { currentPage, pageSize, PaginationComponent }; -}; \ No newline at end of file diff --git a/packages/ui/index.ts b/packages/ui/index.ts index e77ea6c..91d4254 100755 --- a/packages/ui/index.ts +++ b/packages/ui/index.ts @@ -1,17 +1,13 @@ import Constants from "expo-constants"; import { Platform } from "react-native"; -import RolesDropdown from "./src/roles-dropdown"; import { StorageService } from "./src/services/StorageService"; import { ROLE_NAMES, - ROLE_DISPLAY_NAMES, - ROLE_OPTIONS, - BUSINESS_ROLE_OPTIONS, } from "./src/lib/constants"; import { REFUND_STATUS } from "./src/lib/const-strs"; import { colors, colorsType } from "./src/lib/theme-colors"; import { theme } from "./src/theme"; -import MyButton, { MyTextButton } from "./src/components/button"; +import MyButton from "./src/components/button"; import { useTheme, Theme } from "./hooks/theme-context"; import MyTextInput from "./src/components/textinput"; import BottomDialog, { ConfirmationDialog, RawBottomDialog } from "./src/components/dialog"; @@ -22,8 +18,6 @@ import MyTouchableOpacity from "./src/components/touchable-opacity"; import BottomDropdown from "./src/components/bottom-dropdown"; import ImageViewerURI from "./src/components/image-viewer"; import ImageCarousel from "./src/components/ImageCarousel"; -import ImageGallery from "./src/components/ImageGallery"; -import ImageGalleryWithDelete from "./src/components/ImageGalleryWithDelete"; import ImageUploader from "./src/components/ImageUploader"; import ImageUploaderNeo, { ImageUploaderNeoItem, ImageUploaderNeoPayload } from "./src/components/ImageUploaderNeo"; import ProfileImage from "./src/components/profile-image"; @@ -31,21 +25,18 @@ import Checkbox from "./src/components/checkbox"; import AppContainer from "./src/components/app-container"; import tw from "./src/lib/tailwind"; import SearchBar from "./src/components/search-bar"; -import DataTable from "./src/components/data-table"; import Quantifier from "./src/components/quantifier"; import MiniQuantifier from "./src/components/mini-quantifier"; -import TabViewWrapper from "./src/components/tab-view"; import MyFlatList from "./src/components/flat-list"; import useFocusCallback from "./hooks/useFocusCallback"; import useManualRefresh from "./hooks/useManualRefresh"; import { useDrawerTitle } from "./hooks/useDrawerTitle"; import { useMarkDataFetchers } from "./hooks/useMarkDataFetchers"; -import { useIsDevMode } from "./hooks/useIsDevMode"; -import { usePagination } from "./hooks/usePagination"; import { StorageServiceCasual } from "./src/services/StorageServiceCasual"; import DateTimePickerMod from "./src/components/date-time-picker"; import { RefreshProvider, useRefresh } from "./src/lib/refresh-context"; import MyStatusBar from "./src/components/MyStatusBar"; +import { InfoDialog } from "./src/components/info-dialog"; import { updateStatusBarColor, useStatusBarStore } from "./src/lib/status-bar-store"; const isDevMode = Constants.executionEnvironment !== "standalone"; @@ -69,24 +60,19 @@ const isDevMode = Constants.executionEnvironment !== "standalone"; // let BASE_API_URL = "https://raw.freshyo.in"; let BASE_API_URL = "https://worker.freshyo.in"; // let BASE_API_URL = "https://freshyo.technocracy.ovh"; -// let BASE_API_URL = 'http://192.168.100.111:8787'; +// let BASE_API_URL = 'http://192.168.100.120:8787'; // let BASE_API_URL = 'http://192.168.29.176:4000'; // if(isDevMode) { // } export { - RolesDropdown, StorageService, ROLE_NAMES, - ROLE_DISPLAY_NAMES, - ROLE_OPTIONS, - BUSINESS_ROLE_OPTIONS, colors, colorsType, theme, MyButton, - MyTextButton, useTheme, Theme, MyTextInput, @@ -100,8 +86,6 @@ export { BottomDropdown, ImageViewerURI, ImageCarousel, - ImageGallery, - ImageGalleryWithDelete, ImageUploader, ImageUploaderNeo, ImageUploaderNeoItem, @@ -111,10 +95,8 @@ export { AppContainer, tw, SearchBar, - DataTable, Quantifier, MiniQuantifier, - TabViewWrapper, MyFlatList, useFocusCallback, useManualRefresh, @@ -122,13 +104,12 @@ export { BASE_API_URL, useMarkDataFetchers, StorageServiceCasual, - useIsDevMode, - usePagination, REFUND_STATUS, DateTimePickerMod, RefreshProvider, useRefresh, MyStatusBar, + InfoDialog, updateStatusBarColor, useStatusBarStore, }; diff --git a/packages/ui/src/components/ImageGallery.tsx b/packages/ui/src/components/ImageGallery.tsx deleted file mode 100755 index a04ca79..0000000 --- a/packages/ui/src/components/ImageGallery.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react'; -import { View, FlatList, Dimensions, StyleSheet, TouchableOpacity } from 'react-native'; -import { Image } from 'expo-image'; -import ImageViewerURI from './image-viewer'; - -interface ImageGalleryProps { - urls: string[]; - imageHeight?: number; - imageWidth?: number; - columns?: number; -} - -const { width: screenWidth } = Dimensions.get('window'); - -const ImageGallery: React.FC = ({ - urls, - imageHeight = 150, - imageWidth = screenWidth / 3 - 8, // Default to 3 columns with some margin - columns = 3, -}) => { - if (!urls || urls.length === 0) { - return null; - } - - const numColumns = columns; - const containerPadding = 16; - - const renderItem = ({ item }: { item: string }) => ( - - - - ); - - return ( - - index.toString()} - renderItem={renderItem} - showsVerticalScrollIndicator={false} - /> - - ); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - imageContainer: { - margin: 4, - borderRadius: 8, - overflow: 'hidden', - }, - image: { - resizeMode: 'cover', - borderRadius: 8, - }, -}); - -export default ImageGallery; \ No newline at end of file diff --git a/packages/ui/src/components/ImageGalleryWithDelete.tsx b/packages/ui/src/components/ImageGalleryWithDelete.tsx deleted file mode 100644 index b2ec412..0000000 --- a/packages/ui/src/components/ImageGalleryWithDelete.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import React from 'react'; -import { View, FlatList, Dimensions, StyleSheet, TouchableOpacity, Alert } from 'react-native'; -import { Ionicons } from '@expo/vector-icons'; -import ImageViewerURI from './image-viewer'; - -interface ImageGalleryWithDeleteProps { - imageUrls: string[]; - setImageUrls: (urls: string[]) => void; - imageHeight?: number; - imageWidth?: number; - columns?: number; -} - -const { width: screenWidth } = Dimensions.get('window'); - -const ImageGalleryWithDelete: React.FC = ({ - imageUrls, - setImageUrls, - imageHeight = 150, - imageWidth = screenWidth / 3 - 8, // Default to 3 columns with some margin - columns = 3, -}) => { - if (!imageUrls || imageUrls.length === 0) { - return null; - } - - const numColumns = columns; - const containerPadding = 16; - - const handleDeleteImage = (index: number) => { - Alert.alert( - 'Delete Image', - 'Are you sure you want to delete this image?', - [ - { text: 'Cancel', style: 'cancel' }, - { - text: 'Delete', - style: 'destructive', - onPress: () => { - const newUrls = imageUrls.filter((_, i) => i !== index); - setImageUrls(newUrls); - }, - }, - ] - ); - }; - - const renderItem = ({ item, index }: { item: string; index: number }) => ( - - - handleDeleteImage(index)} - > - - - - ); - - return ( - - index.toString()} - renderItem={renderItem} - showsVerticalScrollIndicator={false} - /> - - ); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - imageContainer: { - margin: 4, - borderRadius: 8, - overflow: 'hidden', - position: 'relative', - }, - image: { - resizeMode: 'cover', - borderRadius: 8, - }, - deleteButton: { - position: 'absolute', - top: 4, - right: 4, - backgroundColor: 'rgba(255, 255, 255, 0.8)', - borderRadius: 12, - padding: 2, - }, -}); - -export default ImageGalleryWithDelete; \ No newline at end of file diff --git a/packages/ui/src/components/PaginatedDataTable.tsx b/packages/ui/src/components/PaginatedDataTable.tsx deleted file mode 100755 index 243ff2c..0000000 --- a/packages/ui/src/components/PaginatedDataTable.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react'; -import { DataTable } from 'react-native-paper'; -import dayjs from 'dayjs'; - -// Define the shape of a single token item -interface Token { - id: number; - queueNum: number; - tokenDate: string; - doctorName: string; - patientName: string; - status: string; -} - -// Define the props for the component -interface PaginatedDataTableProps { - tokens: Token[]; - page: number; - numberOfPages: number; - onPageChange: (page: number) => void; - from: number; - to: number; - totalCount: number; - numberOfItemsPerPageList: number[]; - itemsPerPage: number; - onItemsPerPageChange: (itemsPerPage: number) => void; -} - -const PaginatedDataTable: React.FC = ({ - tokens, - page, - numberOfPages, - onPageChange, - from, - to, - totalCount, - numberOfItemsPerPageList, - itemsPerPage, - onItemsPerPageChange, -}) => { - return ( - - - Q.No - Date - Doctor - Patient - Status - - - {tokens.map((token) => ( - - {token.queueNum} - {dayjs(token.tokenDate).format('DD-MM-YY')} - {token.doctorName} - {token.patientName} - {token.status} - - ))} - - - - ); -}; - -export default PaginatedDataTable; \ No newline at end of file diff --git a/packages/ui/src/components/data-table.tsx b/packages/ui/src/components/data-table.tsx deleted file mode 100755 index 483a21d..0000000 --- a/packages/ui/src/components/data-table.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react'; -import { StyleProp, ViewStyle } from 'react-native'; -import { DataTable as PaperDataTable } from 'react-native-paper'; - -// Define a generic column configuration -export interface Column { - header: string; - accessor: keyof T; - style?: StyleProp; - render?: (row: T) => React.ReactNode; -} - -// Define the props for the component, using a generic type T -interface DataTableProps { - data: T[]; - columns: Column[]; - page: number; - numberOfPages: number; - onPageChange: (page: number) => void; - from: number; - to: number; - totalCount: number; - numberOfItemsPerPageList: number[]; - itemsPerPage: number; - onItemsPerPageChange: (itemsPerPage: number) => void; -} - -const DataTable = ({ // The data objects must have a unique 'id' property - data, - columns, - page, - numberOfPages, - onPageChange, - from, - to, - totalCount, - numberOfItemsPerPageList, - itemsPerPage, - onItemsPerPageChange, -}: DataTableProps) => { - return ( - - - {columns.map((col, index) => ( - - {col.header} - - ))} - - - {data.map((row) => ( - - {columns.map((col, index) => ( - - {col.render ? col.render(row) : String(row[col.accessor] ?? '')} - - ))} - - ))} - - - - ); -}; - -export default DataTable; \ No newline at end of file diff --git a/packages/ui/src/components/tab-view.tsx b/packages/ui/src/components/tab-view.tsx deleted file mode 100644 index 4cd3de1..0000000 --- a/packages/ui/src/components/tab-view.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { TabView, TabViewProps, Route, TabBar } from 'react-native-tab-view'; -import { useTheme } from 'common-ui'; - -interface TabViewWrapperProps extends TabViewProps { - // Additional props can be added here if needed -} - -const TabViewWrapper: React.FC = (props) => { - const { theme } = useTheme(); - - const renderTabBar = (tabBarProps: any) => ( - - ); - - return ; -}; - -export default TabViewWrapper; \ No newline at end of file diff --git a/packages/ui/src/lib/constants.ts b/packages/ui/src/lib/constants.ts index 370e580..d09d662 100755 --- a/packages/ui/src/lib/constants.ts +++ b/packages/ui/src/lib/constants.ts @@ -10,36 +10,4 @@ export const ROLE_NAMES = { DOCTOR_SECRETARY: 'doctor_secretary' }; -/** - * Constants for display names of roles for UI presentation - */ -export const ROLE_DISPLAY_NAMES = { - [ROLE_NAMES.ADMIN]: 'Administrator', - [ROLE_NAMES.GENERAL_USER]: 'General User', - [ROLE_NAMES.HOSPITAL_ADMIN]: 'Hospital Admin', - [ROLE_NAMES.DOCTOR]: 'Doctor', - [ROLE_NAMES.HOSPITAL_ASSISTANT]: 'Hospital Assistant', - [ROLE_NAMES.DOCTOR_SECRETARY]: 'Doctor Secretary' -}; - -/** - * Role options for dropdowns in forms - */ -export const ROLE_OPTIONS = [ - { label: ROLE_DISPLAY_NAMES[ROLE_NAMES.HOSPITAL_ADMIN], value: ROLE_NAMES.HOSPITAL_ADMIN }, - { label: ROLE_DISPLAY_NAMES[ROLE_NAMES.DOCTOR], value: ROLE_NAMES.DOCTOR }, - { label: ROLE_DISPLAY_NAMES[ROLE_NAMES.HOSPITAL_ASSISTANT], value: ROLE_NAMES.HOSPITAL_ASSISTANT }, - { label: ROLE_DISPLAY_NAMES[ROLE_NAMES.DOCTOR_SECRETARY], value: ROLE_NAMES.DOCTOR_SECRETARY } -]; - -/** - * Business role options (subset of roles that can be assigned to business users) - */ -export const BUSINESS_ROLE_OPTIONS = [ - { label: ROLE_DISPLAY_NAMES[ROLE_NAMES.HOSPITAL_ADMIN], value: ROLE_NAMES.HOSPITAL_ADMIN }, - { label: ROLE_DISPLAY_NAMES[ROLE_NAMES.DOCTOR], value: ROLE_NAMES.DOCTOR }, - { label: ROLE_DISPLAY_NAMES[ROLE_NAMES.HOSPITAL_ASSISTANT], value: ROLE_NAMES.HOSPITAL_ASSISTANT }, - { label: ROLE_DISPLAY_NAMES[ROLE_NAMES.DOCTOR_SECRETARY], value: ROLE_NAMES.DOCTOR_SECRETARY } -]; - export const GENDERS = ['Male', 'Female'] \ No newline at end of file diff --git a/packages/ui/src/roles-dropdown.tsx b/packages/ui/src/roles-dropdown.tsx deleted file mode 100755 index bdce9d7..0000000 --- a/packages/ui/src/roles-dropdown.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react' -import {View,Text} from 'react-native'; - -interface Props {} - -function RolesDropdown(props: Props) { - const {} = props - - return ( - - RolesDropdown - - ) -} - -export default RolesDropdown