diff --git a/.commandcode/settings.json b/.commandcode/settings.json index 185d922..2668a61 100644 --- a/.commandcode/settings.json +++ b/.commandcode/settings.json @@ -5,7 +5,10 @@ "Shell(npx tsc --noEmit 2 >& 1)", "Shell(grep:*)", "Shell(npx tsc --noEmit -p packages/shared/tsconfig.json 2 >& 1)", - "Shell(cp:*)" + "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)" ], "deny": [], "defaultMode": "default" diff --git a/.commandcode/taste/taste/taste.md b/.commandcode/taste/taste/taste.md index dca9b0e..815ed5f 100644 --- a/.commandcode/taste/taste/taste.md +++ b/.commandcode/taste/taste/taste.md @@ -19,3 +19,4 @@ - 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 diff --git a/apps/admin-ui/app/(drawer)/_layout.tsx b/apps/admin-ui/app/(drawer)/_layout.tsx index 79dd68b..a559e81 100644 --- a/apps/admin-ui/app/(drawer)/_layout.tsx +++ b/apps/admin-ui/app/(drawer)/_layout.tsx @@ -1,7 +1,6 @@ import { Drawer } from "expo-router/drawer"; import { DrawerContentScrollView, DrawerItem } from "@react-navigation/drawer"; import { useRouter, Redirect } from "expo-router"; -import { useNavigation, DrawerActions } from "@react-navigation/native"; import { TouchableOpacity, DeviceEventEmitter, @@ -13,6 +12,25 @@ import { REFRESH_EVENT } from "common-ui/src/lib/const-strs"; import { useStaffAuth } from "@/components/context/staff-auth-context"; import { tw, MyText, theme } from "common-ui"; +const SCREEN_TITLES: Record = { + index: "Dashboard", + products: "Products", + "prices-overview": "Prices Overview", + "product-groupings": "Product Groupings", + "dashboard-banners": "Dashboard Banners", + slots: "Slots", + complaints: "Complaints", + "manage-orders": "Manage Orders", + coupons: "Coupons", + "vendor-snippets": "Vendor Snippets", + stores: "Stores", + "user-management": "User Management", + "send-notifications": "Send Notifications", + "product-tags": "Product Tags", + "rebalance-orders": "Rebalance Orders", + "customize-app": "Customize App", +}; + function CustomDrawerContent() { const router = useRouter(); const { logout, staff } = useStaffAuth(); @@ -32,121 +50,108 @@ function CustomDrawerContent() { )} router.push("/(drawer)/dashboard" as any)} + onPress={() => router.dismissTo("/(drawer)/dashboard" as any)} icon={({ color, size }) => ( )} /> - {/* router.push("/(drawer)/add-product" as any)} - icon={({ color, size }) => ( - - )} - /> */} - router.push("/(drawer)/products" as any)} - icon={({ color, size }) => ( - - )} - /> - router.push("/(drawer)/prices-overview" as any)} - icon={({ color, size }) => ( - - )} - /> - router.push("/(drawer)/product-groupings" as any)} - icon={({ color, size }) => ( - - )} - /> - router.push("/(drawer)/dashboard-banners" as any)} - icon={({ color, size }) => ( - - )} - /> - router.push("/(drawer)/slots" as any)} - icon={({ color, size }) => ( - - )} - /> - {/* router.push("/(drawer)/edit-product" as any)} + router.push("/(drawer)/dashboard/products" as any)} icon={({ color, size }) => ( - + )} - /> */} + /> + router.push("/(drawer)/dashboard/prices-overview" as any)} + icon={({ color, size }) => ( + + )} + /> + router.push("/(drawer)/dashboard/product-groupings" as any)} + icon={({ color, size }) => ( + + )} + /> + router.push("/(drawer)/dashboard/dashboard-banners" as any)} + icon={({ color, size }) => ( + + )} + /> + router.push("/(drawer)/dashboard/slots" as any)} + icon={({ color, size }) => ( + + )} + /> router.push("/(drawer)/complaints" as any)} + onPress={() => router.push("/(drawer)/dashboard/complaints" as any)} icon={({ color, size }) => ( )} /> router.push("/(drawer)/manage-orders" as any)} + onPress={() => router.push("/(drawer)/dashboard/manage-orders" as any)} icon={({ color, size }) => ( )} /> - router.push("coupons" as any)} - icon={({ color, size }) => ( - - )} - /> - router.push("vendor-snippets" as any)} - icon={({ color, size }) => ( - - )} - /> - router.push("/(drawer)/stores" as any)} - icon={({ color, size }) => ( - - )} - /> - router.push("/(drawer)/user-management" as any)} - icon={({ color, size }) => ( - - )} - /> - router.push("/(drawer)/send-notifications" as any)} - icon={({ color, size }) => ( - - )} - /> - logout()} - icon={({ color, size }) => ( - - )} - /> + router.push("/(drawer)/dashboard/coupons" as any)} + icon={({ color, size }) => ( + + )} + /> + router.push("/(drawer)/dashboard/vendor-snippets" as any)} + icon={({ color, size }) => ( + + )} + /> + router.push("/(drawer)/dashboard/stores" as any)} + icon={({ color, size }) => ( + + )} + /> + router.push("/(drawer)/dashboard/user-management" as any)} + icon={({ color, size }) => ( + + )} + /> + router.push("/(drawer)/dashboard/send-notifications" as any)} + icon={({ color, size }) => ( + + )} + /> + logout()} + icon={({ color, size }) => ( + + )} + /> ); } export default function Layout() { + const router = useRouter(); const { isLoggedIn, isLoading } = useStaffAuth(); if (isLoading) { @@ -163,74 +168,72 @@ export default function Layout() { return ( ({ - swipeEnabled: false, - headerShown: true, - headerStyle: { - backgroundColor: theme.colors.gray1, - shadowOpacity: 0, - shadowRadius: 0, - shadowOffset: { height: 0, width: 0 }, - elevation: 0, - }, - headerTitleAlign: "center", - headerLeft: () => ( - (navigation as any).openDrawer()} - style={{ - marginLeft: 15, - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: "#f2f2f2", - justifyContent: "center", - alignItems: "center", - }} - > - - - ), - headerRight: () => ( - { - DeviceEventEmitter.emit(REFRESH_EVENT); - }} - > - - - ), - })} + screenOptions={({ navigation }) => { + const state = navigation.getState(); + const focusedRoute = state?.routes?.[state?.index ?? 0]; + const dashboardStack = (focusedRoute as any)?.state; + const nestedIndex = dashboardStack?.index ?? 0; + const canGoBack = nestedIndex > 0; + const nestedRoute = dashboardStack?.routes?.[nestedIndex]; + const title = SCREEN_TITLES[nestedRoute?.name ?? ""] ?? "Dashboard"; + + return { + swipeEnabled: false, + headerShown: true, + headerStyle: { + backgroundColor: theme.colors.gray1, + shadowOpacity: 0, + shadowRadius: 0, + shadowOffset: { height: 0, width: 0 }, + elevation: 0, + }, + headerTitle: title, + headerTitleAlign: "center", + headerLeft: () => ( + + canGoBack ? router.back() : (navigation as any).openDrawer() + } + style={{ + marginLeft: 15, + width: 40, + height: 40, + borderRadius: 20, + backgroundColor: "#f2f2f2", + justifyContent: "center", + alignItems: "center", + }} + > + + + ), + headerRight: () => ( + { + DeviceEventEmitter.emit(REFRESH_EVENT); + }} + > + + + ), + }; + }} > - - - - - - - - - - - - - - - - - + + ); } diff --git a/apps/admin-ui/app/(drawer)/dashboard/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/_layout.tsx index c9990f0..cc1cb72 100644 --- a/apps/admin-ui/app/(drawer)/dashboard/_layout.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/_layout.tsx @@ -2,14 +2,41 @@ import { Stack } from "expo-router"; export default function Layout() { return ( - + + + + + + + + + + + + + + + + ); -} \ No newline at end of file +} diff --git a/apps/admin-ui/app/(drawer)/complaints/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/complaints/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/complaints/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/complaints/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/complaints/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/complaints/index.tsx similarity index 98% rename from apps/admin-ui/app/(drawer)/complaints/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/complaints/index.tsx index 42cd593..1fc927e 100644 --- a/apps/admin-ui/app/(drawer)/complaints/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/complaints/index.tsx @@ -47,11 +47,11 @@ export default function Complaints() { }, [hasNextPage, isFetchingNextPage, fetchNextPage]); const handleUserPress = useCallback((userId: number) => { - router.push(`/(drawer)/user-management/${userId}`); + router.push(`/(drawer)/dashboard/user-management/${userId}`); }, [router]); const handleOrderPress = useCallback((orderId: number) => { - router.push(`/(drawer)/manage-orders/order-details/${orderId}`); + router.push(`/(drawer)/dashboard/manage-orders/order-details/${orderId}`); }, [router]); const handleMarkResolved = (id: number) => { diff --git a/apps/admin-ui/app/(drawer)/coupons/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/coupons/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/coupons/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/coupons/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/coupons/create.tsx b/apps/admin-ui/app/(drawer)/dashboard/coupons/create.tsx similarity index 70% rename from apps/admin-ui/app/(drawer)/coupons/create.tsx rename to apps/admin-ui/app/(drawer)/dashboard/coupons/create.tsx index 53c4605..ba3bbac 100644 --- a/apps/admin-ui/app/(drawer)/coupons/create.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/coupons/create.tsx @@ -24,9 +24,9 @@ export default function CreateCoupon() { } ) - const handleCreateCoupon = (values: any) => { + const handleCreateCoupon = async (values: any) => { console.log('Form values:', values); // Debug log - const { isReservedCoupon, ...rest } = values; + const { isReservedCoupon, couponCodes, ...rest } = values; // Transform targetUsers array to targetUser for backend compatibility const payload = { ...rest, @@ -35,6 +35,24 @@ export default function CreateCoupon() { delete payload.targetUsers; console.log('Payload:', payload); // Debug log + if (isReservedCoupon && Array.isArray(couponCodes) && couponCodes.length > 0) { + // Create one reserved coupon per code, same config + const codes = couponCodes.map((c: string) => c.trim()).filter(Boolean); + try { + for (const code of codes) { + await createReservedCoupon.mutateAsync({ ...payload, couponCode: code }); + } + await refetchCoupons() + await refetchReservedCoupons() + Alert.alert('Success', `${codes.length} reserved coupon${codes.length > 1 ? 's' : ''} created successfully`, [ + { text: 'OK', onPress: () => router.back() } + ]); + } catch (error: any) { + Alert.alert('Error', error.message || 'Failed to create reserved coupons'); + } + return; + } + const mutation = isReservedCoupon ? createReservedCoupon : createCoupon; const isLoading = isReservedCoupon ? createReservedCoupon.isPending : createCoupon.isPending; diff --git a/apps/admin-ui/app/(drawer)/coupons/edit/[id].tsx b/apps/admin-ui/app/(drawer)/dashboard/coupons/edit/[id].tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/coupons/edit/[id].tsx rename to apps/admin-ui/app/(drawer)/dashboard/coupons/edit/[id].tsx diff --git a/apps/admin-ui/app/(drawer)/coupons/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/coupons/index.tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/coupons/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/coupons/index.tsx index 32d7f9e..07f5d3f 100644 --- a/apps/admin-ui/app/(drawer)/coupons/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/coupons/index.tsx @@ -90,7 +90,7 @@ const CouponItem = ({ item, onDelete }: { item: any; onDelete: (id: number) => v router.push(`/coupons/edit/${item.id}`)} + onPress={() => router.push(`/(drawer)/dashboard/coupons/edit/${item.id}`)} style={tw`bg-blue-500 p-3 rounded-lg shadow-md flex-1 flex-row items-center justify-center`} > @@ -497,7 +497,7 @@ export default function Coupons() { )} /> router.push('/coupons/create')} + onPress={() => router.push('/(drawer)/dashboard/coupons/create')} activeOpacity={0.95} style={{ position: 'absolute', bottom: 32, right: 24, zIndex: 100 }} > diff --git a/apps/admin-ui/app/(drawer)/coupons/reserved-coupons/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/coupons/reserved-coupons/index.tsx similarity index 98% rename from apps/admin-ui/app/(drawer)/coupons/reserved-coupons/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/coupons/reserved-coupons/index.tsx index d5f82c4..6c32c32 100644 --- a/apps/admin-ui/app/(drawer)/coupons/reserved-coupons/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/coupons/reserved-coupons/index.tsx @@ -217,7 +217,7 @@ export default function ReservedCoupons() { No Reserved Coupons Yet Create your first reserved coupon to start offering secret discounts - router.push('/coupons/create')} style={tw`bg-blue-500`}> + router.push('/(drawer)/dashboard/coupons/create')} style={tw`bg-blue-500`}> Create Reserved Coupon @@ -230,7 +230,7 @@ export default function ReservedCoupons() { {/* FAB for Add New Reserved Coupon */} router.push('/coupons/create')} + onPress={() => router.push('/(drawer)/dashboard/coupons/create')} activeOpacity={0.95} style={{ position: 'absolute', bottom: 32, right: 24, zIndex: 100 }} > diff --git a/apps/admin-ui/app/(drawer)/customize-app/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/customize-app/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/customize-app/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/customize-app/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/customize-app/all-items-order.tsx b/apps/admin-ui/app/(drawer)/dashboard/customize-app/all-items-order.tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/customize-app/all-items-order.tsx rename to apps/admin-ui/app/(drawer)/dashboard/customize-app/all-items-order.tsx index d12229e..aad9ae1 100644 --- a/apps/admin-ui/app/(drawer)/customize-app/all-items-order.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/customize-app/all-items-order.tsx @@ -18,7 +18,7 @@ import { MyTouchableOpacity, } from "common-ui"; import { useRouter } from "expo-router"; -import { trpc } from "../../../src/trpc-client"; +import { trpc } from "../../../../src/trpc-client"; import MaterialIcons from "@expo/vector-icons/MaterialIcons"; import { useQueryClient } from "@tanstack/react-query"; diff --git a/apps/admin-ui/app/(drawer)/customize-app/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/customize-app/index.tsx similarity index 97% rename from apps/admin-ui/app/(drawer)/customize-app/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/customize-app/index.tsx index 4c6028d..3b908b4 100644 --- a/apps/admin-ui/app/(drawer)/customize-app/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/customize-app/index.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { View, ScrollView, Alert } from 'react-native'; import { Formik } from 'formik'; import { MyText, MyTextInput, MyTouchableOpacity, tw, AppContainer, Checkbox } from 'common-ui'; -import { trpc } from '../../../src/trpc-client'; +import { trpc } from '../../../../src/trpc-client'; import { useRouter } from 'expo-router'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; @@ -71,7 +71,7 @@ const ConstantInput: React.FC = ({ constantKey, value, setFi {CONST_LABELS[constantKey] || constantKey} router.push('/(drawer)/customize-app/popular-items')} + onPress={() => router.push('/(drawer)/dashboard/customize-app/popular-items')} style={tw`bg-blue-50 border-2 border-dashed border-blue-200 p-4 rounded-lg flex-row items-center justify-center`} > @@ -93,7 +93,7 @@ const ConstantInput: React.FC = ({ constantKey, value, setFi {CONST_LABELS[constantKey] || constantKey} router.push('/(drawer)/customize-app/all-items-order')} + onPress={() => router.push('/(drawer)/dashboard/customize-app/all-items-order')} style={tw`bg-green-50 border-2 border-dashed border-green-200 p-4 rounded-lg flex-row items-center justify-center`} > diff --git a/apps/admin-ui/app/(drawer)/customize-app/popular-items.tsx b/apps/admin-ui/app/(drawer)/dashboard/customize-app/popular-items.tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/customize-app/popular-items.tsx rename to apps/admin-ui/app/(drawer)/dashboard/customize-app/popular-items.tsx index dd139dd..6101832 100644 --- a/apps/admin-ui/app/(drawer)/customize-app/popular-items.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/customize-app/popular-items.tsx @@ -19,9 +19,9 @@ import { BottomDropdown, MyTouchableOpacity, } from "common-ui"; -import ProductsSelector from "../../../components/ProductsSelector"; +import ProductsSelector from "../../../../components/ProductsSelector"; import { useRouter } from "expo-router"; -import { trpc } from "../../../src/trpc-client"; +import { trpc } from "../../../../src/trpc-client"; import MaterialIcons from "@expo/vector-icons/MaterialIcons"; import { useQueryClient } from "@tanstack/react-query"; diff --git a/apps/admin-ui/app/(drawer)/dashboard-banners/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/dashboard-banners/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/dashboard-banners/create.tsx b/apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/create.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/dashboard-banners/create.tsx rename to apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/create.tsx diff --git a/apps/admin-ui/app/(drawer)/dashboard-banners/edit/[id].tsx b/apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/edit/[id].tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/dashboard-banners/edit/[id].tsx rename to apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/edit/[id].tsx diff --git a/apps/admin-ui/app/(drawer)/dashboard-banners/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/index.tsx similarity index 98% rename from apps/admin-ui/app/(drawer)/dashboard-banners/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/index.tsx index 9b04ad4..dbc31d9 100644 --- a/apps/admin-ui/app/(drawer)/dashboard-banners/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/dashboard-banners/index.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { View, ScrollView, TouchableOpacity, Alert, Image, RefreshControl } from 'react-native'; import { AppContainer, MyText, tw, MyTouchableOpacity } from 'common-ui'; -import { trpc } from '../../../src/trpc-client'; +import { trpc } from '../../../../src/trpc-client'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; import { useRouter } from 'expo-router'; @@ -180,7 +180,7 @@ export default function DashboardBanners() { }; const handleEdit = (banner: Banner) => { - router.push(`/dashboard-banners/edit/${banner.id}` as any); + router.push(`/(drawer)/dashboard/dashboard-banners/edit/${banner.id}` as any); }; const handleDelete = (id: number) => { @@ -207,7 +207,7 @@ export default function DashboardBanners() { }; const handleCreate = () => { - router.push('/dashboard-banners/create' as any); + router.push('/(drawer)/dashboard/dashboard-banners/create' as any); }; if (isLoading) { diff --git a/apps/admin-ui/app/(drawer)/dashboard/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/index.tsx index c7f8d4f..003723e 100644 --- a/apps/admin-ui/app/(drawer)/dashboard/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/index.tsx @@ -63,13 +63,13 @@ export default function Dashboard() { const handleManageOrdersPress = () => { - setNavigationTarget('/manage-orders/orders'); - router.push('/(drawer)/manage-orders'); + setNavigationTarget('/(drawer)/dashboard/manage-orders/orders'); + router.push('/(drawer)/dashboard/manage-orders'); }; const handleDeliverySequencesPress = () => { - setNavigationTarget('/manage-orders/delivery-sequences'); - router.push('/(drawer)/manage-orders'); + setNavigationTarget('/(drawer)/dashboard/manage-orders/delivery-sequences'); + router.push('/(drawer)/dashboard/manage-orders'); }; const menuItems: MenuItem[] = [ @@ -77,7 +77,7 @@ export default function Dashboard() { title: 'Manage Orders', icon: 'shopping-bag', description: 'View and manage customer orders', - route: '/(drawer)/manage-orders', + route: '/(drawer)/dashboard/manage-orders', category: 'orders', iconColor: '#10B981', iconBg: '#D1FAE5', @@ -87,7 +87,7 @@ export default function Dashboard() { title: 'Delivery Sequences', icon: 'alt-route', description: 'Plan and optimize delivery routes', - route: '/manage-orders/delivery-sequences', + route: '/(drawer)/dashboard/manage-orders/delivery-sequences', category: 'orders', iconColor: '#8B5CF6', iconBg: '#EDE9FE', @@ -97,7 +97,7 @@ export default function Dashboard() { title: 'Delivery Slots', icon: 'schedule', description: 'Configure delivery times', - route: '/(drawer)/slots' as any, + route: '/(drawer)/dashboard/slots' as any, category: 'quick', iconColor: '#06B6D4', iconBg: '#CFFAFE', @@ -107,7 +107,7 @@ export default function Dashboard() { title: 'Add Product', icon: 'add-circle', description: 'Create a new product listing', - route: '/products/add', + route: '/(drawer)/dashboard/products/add', category: 'quick', iconColor: theme.colors.brand500, iconBg: theme.colors.brand50, @@ -116,7 +116,7 @@ export default function Dashboard() { title: 'Complaints', icon: 'report-problem', description: 'Handle customer complaints', - route: '/(drawer)/complaints', + route: '/(drawer)/dashboard/complaints', category: 'quick', iconColor: '#F59E0B', iconBg: '#FEF3C7', @@ -126,7 +126,7 @@ export default function Dashboard() { title: 'Products', icon: 'inventory-2', description: 'Manage product catalog', - route: '/(drawer)/products', + route: '/(drawer)/dashboard/products', category: 'products', iconColor: '#6366F1', iconBg: '#E0E7FF', @@ -135,7 +135,7 @@ export default function Dashboard() { title: 'Prices Overview', icon: 'attach-money', description: 'Update product pricing', - route: '/(drawer)/prices-overview', + route: '/(drawer)/dashboard/prices-overview', category: 'products', iconColor: '#059669', iconBg: '#ECFDF5', @@ -144,7 +144,7 @@ export default function Dashboard() { title: 'Product Tags', icon: 'label', description: 'Organize with tags', - route: '/(drawer)/product-tags', + route: '/(drawer)/dashboard/product-tags', category: 'products', iconColor: '#EC4899', iconBg: '#FCE7F3', @@ -153,7 +153,7 @@ export default function Dashboard() { title: 'Product Groupings', icon: 'category', description: 'Group products together', - route: '/(drawer)/product-groupings', + route: '/(drawer)/dashboard/product-groupings', category: 'products', iconColor: '#8B5CF6', iconBg: '#F3E8FF', @@ -162,7 +162,7 @@ export default function Dashboard() { title: 'Stores', icon: 'store', description: 'Manage store locations', - route: '/(drawer)/stores', + route: '/(drawer)/dashboard/stores', category: 'settings', iconColor: '#14B8A6', iconBg: '#CCFBF1', @@ -171,7 +171,7 @@ export default function Dashboard() { title: 'Coupons', icon: 'local-offer', description: 'Create discount coupons', - route: '/(drawer)/coupons', + route: '/(drawer)/dashboard/coupons', category: 'marketing', iconColor: '#F97316', iconBg: '#FFEDD5', @@ -180,7 +180,7 @@ export default function Dashboard() { title: 'App Constants', icon: 'settings-applications', description: 'Customize app settings', - route: '/(drawer)/customize-app', + route: '/(drawer)/dashboard/customize-app', category: 'settings', iconColor: '#7C3AED', iconBg: '#F3E8FF', @@ -189,7 +189,7 @@ export default function Dashboard() { title: 'User Management', icon: 'people', description: 'View and manage all users', - route: '/(drawer)/user-management', + route: '/(drawer)/dashboard/user-management', category: 'users', iconColor: '#0EA5E9', iconBg: '#E0F2FE', @@ -198,7 +198,7 @@ export default function Dashboard() { title: 'Send Notifications', icon: 'campaign', description: 'Send push notifications to users', - route: '/(drawer)/send-notifications', + route: '/(drawer)/dashboard/send-notifications', category: 'users', iconColor: '#8B5CF6', iconBg: '#F3E8FF', diff --git a/apps/admin-ui/app/(drawer)/manage-orders/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/manage-orders/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/manage-orders/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/manage-orders/delivery-sequences/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/delivery-sequences/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/manage-orders/delivery-sequences/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/manage-orders/delivery-sequences/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/manage-orders/delivery-sequences/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/delivery-sequences/index.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/manage-orders/delivery-sequences/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/manage-orders/delivery-sequences/index.tsx diff --git a/apps/admin-ui/app/(drawer)/manage-orders/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/index.tsx similarity index 92% rename from apps/admin-ui/app/(drawer)/manage-orders/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/manage-orders/index.tsx index 2cb4b87..2411891 100644 --- a/apps/admin-ui/app/(drawer)/manage-orders/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/index.tsx @@ -46,7 +46,7 @@ export default function ManageOrders() { Alert.alert('Flash Deliveries', 'Flash deliveries do not have delivery sequences. Use the Orders menu to manage flash deliveries.'); return; } - router.push(`/manage-orders/delivery-sequences?slotId=${selectedSlotId}`); + router.push(`/(drawer)/dashboard/manage-orders/delivery-sequences?slotId=${selectedSlotId}`); }, }, { @@ -55,9 +55,9 @@ export default function ManageOrders() { color: 'bg-cyan-500', onPress: () => { if (selectedSlotId === 'flash') { - router.push('/manage-orders/orders?filter=flash'); + router.push('/(drawer)/dashboard/manage-orders/orders?filter=flash'); } else { - router.push('/manage-orders/orders'); + router.push('/(drawer)/dashboard/manage-orders/orders'); } }, }, diff --git a/apps/admin-ui/app/(drawer)/manage-orders/order-details/[id].tsx b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/order-details/[id].tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/manage-orders/order-details/[id].tsx rename to apps/admin-ui/app/(drawer)/dashboard/manage-orders/order-details/[id].tsx index 43c45c4..0b174d6 100644 --- a/apps/admin-ui/app/(drawer)/manage-orders/order-details/[id].tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/order-details/[id].tsx @@ -378,7 +378,7 @@ export default function OrderDetails() { {/* Customer Details */} order.userId && router.push(`/(drawer)/user-management/${order.userId}`)} + onPress={() => order.userId && router.push(`/(drawer)/dashboard/user-management/${order.userId}`)} activeOpacity={0.7} style={tw`bg-white p-5 rounded-2xl shadow-sm mb-4 border border-gray-100`} > @@ -784,7 +784,7 @@ export default function OrderDetails() { )} router.push("/(drawer)/manage-orders")} + onPress={() => router.push("/(drawer)/dashboard/manage-orders")} style={tw`bg-gray-900 rounded-xl py-4 items-center shadow-lg`} > diff --git a/apps/admin-ui/app/(drawer)/manage-orders/order-details/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/order-details/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/manage-orders/order-details/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/manage-orders/order-details/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/manage-orders/orders/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/orders/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/manage-orders/orders/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/manage-orders/orders/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/manage-orders/orders/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/orders/index.tsx similarity index 98% rename from apps/admin-ui/app/(drawer)/manage-orders/orders/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/manage-orders/orders/index.tsx index 3d7a988..024db6f 100644 --- a/apps/admin-ui/app/(drawer)/manage-orders/orders/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/manage-orders/orders/index.tsx @@ -284,17 +284,17 @@ const OrderItem = ({ order, refetch }: { order: OrderType; refetch: () => void } > - {order.items.length} {order.items.length === 1 ? 'item' : 'items'} + {`${order.items.length} ${order.items.length === 1 ? 'item' : 'items'}`} {order.isFlashDelivery && ( - + )} Total: - ₹{order.totalAmount} + {`₹${order.totalAmount}`} @@ -315,8 +315,8 @@ const OrderItem = ({ order, refetch }: { order: OrderType; refetch: () => void } )} {order.discountAmount && ( - Discount: ₹{order.discountAmount} - + {`Discount: ₹${order.discountAmount}`} + )} @@ -353,7 +353,7 @@ const OrderItem = ({ order, refetch }: { order: OrderType; refetch: () => void } Delivery Charge - ₹{order.deliveryCharge} + {`₹${order.deliveryCharge}`} )} @@ -407,13 +407,13 @@ const OrderItem = ({ order, refetch }: { order: OrderType; refetch: () => void } )} - Total: ₹{order.totalAmount} + {`Total: ₹${order.totalAmount}`} {order.items.map((item, idx) => ( - {item.quantity} x {item.productSize}{item.unit} + {`${item.quantity} x ${item.productSize}${item.unit}`} {item.name.length > 30 ? `${item.name.substring(0, 30)}...` : item.name} diff --git a/apps/admin-ui/app/(drawer)/prices-overview/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/prices-overview/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/prices-overview/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/prices-overview/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/prices-overview/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/prices-overview/index.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/prices-overview/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/prices-overview/index.tsx diff --git a/apps/admin-ui/app/(drawer)/product-groupings/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/product-groupings/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/product-groupings/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-groupings/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/product-groupings/create.tsx b/apps/admin-ui/app/(drawer)/dashboard/product-groupings/create.tsx similarity index 84% rename from apps/admin-ui/app/(drawer)/product-groupings/create.tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-groupings/create.tsx index b3d3b09..eda1d64 100644 --- a/apps/admin-ui/app/(drawer)/product-groupings/create.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/product-groupings/create.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { View } from 'react-native'; import { AppContainer } from 'common-ui'; -import ProductGroupForm from '../../../components/ProductGroupForm'; +import ProductGroupForm from '../../../../components/ProductGroupForm'; import { useRouter } from 'expo-router'; export default function CreateProductGroup() { diff --git a/apps/admin-ui/app/(drawer)/product-groupings/edit/[id].tsx b/apps/admin-ui/app/(drawer)/dashboard/product-groupings/edit/[id].tsx similarity index 94% rename from apps/admin-ui/app/(drawer)/product-groupings/edit/[id].tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-groupings/edit/[id].tsx index 78d57bb..1437519 100644 --- a/apps/admin-ui/app/(drawer)/product-groupings/edit/[id].tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/product-groupings/edit/[id].tsx @@ -1,7 +1,7 @@ import React from 'react'; import { View } from 'react-native'; import { AppContainer, MyText } from 'common-ui'; -import ProductGroupForm from '../../../../components/ProductGroupForm'; +import ProductGroupForm from '../../../../../components/ProductGroupForm'; import { useRouter, useLocalSearchParams } from 'expo-router'; import { trpc } from '@/src/trpc-client'; diff --git a/apps/admin-ui/app/(drawer)/product-groupings/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/product-groupings/index.tsx similarity index 97% rename from apps/admin-ui/app/(drawer)/product-groupings/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-groupings/index.tsx index 8360d80..de4806c 100644 --- a/apps/admin-ui/app/(drawer)/product-groupings/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/product-groupings/index.tsx @@ -10,7 +10,7 @@ import { MyTouchableOpacity, BottomDialog, } from "common-ui"; -import { trpc } from "../../../src/trpc-client"; +import { trpc } from "../../../../src/trpc-client"; import MaterialIcons from "@expo/vector-icons/MaterialIcons"; import { LinearGradient } from "expo-linear-gradient"; import dayjs from "dayjs"; @@ -143,11 +143,11 @@ export default function ProductGroupings() { }); const handleCreate = () => { - router.push("/product-groupings/create"); + router.push("/(drawer)/dashboard/product-groupings/create"); }; const handleEdit = (group: ProductGroup) => { - router.push(`/product-groupings/edit/${group.id}`); + router.push(`/(drawer)/dashboard/product-groupings/edit/${group.id}`); }; const handleDelete = (id: number) => { diff --git a/apps/admin-ui/app/(drawer)/product-tags/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/product-tags/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/product-tags/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-tags/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/product-tags/add.tsx b/apps/admin-ui/app/(drawer)/dashboard/product-tags/add.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/product-tags/add.tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-tags/add.tsx diff --git a/apps/admin-ui/app/(drawer)/product-tags/edit/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/product-tags/edit/index.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/product-tags/edit/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-tags/edit/index.tsx diff --git a/apps/admin-ui/app/(drawer)/product-tags/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/product-tags/index.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/product-tags/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-tags/index.tsx diff --git a/apps/admin-ui/app/(drawer)/product-tags/order.tsx b/apps/admin-ui/app/(drawer)/dashboard/product-tags/order.tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/product-tags/order.tsx rename to apps/admin-ui/app/(drawer)/dashboard/product-tags/order.tsx index 7b542f4..06105a0 100644 --- a/apps/admin-ui/app/(drawer)/product-tags/order.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/product-tags/order.tsx @@ -18,7 +18,7 @@ import { MyTouchableOpacity, } from 'common-ui'; import { useRouter } from 'expo-router'; -import { trpc } from '../../../src/trpc-client'; +import { trpc } from '../../../../src/trpc-client'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; import { useQueryClient } from '@tanstack/react-query'; diff --git a/apps/admin-ui/app/(drawer)/products/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/products/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/products/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/products/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/products/add.tsx b/apps/admin-ui/app/(drawer)/dashboard/products/add.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/products/add.tsx rename to apps/admin-ui/app/(drawer)/dashboard/products/add.tsx diff --git a/apps/admin-ui/app/(drawer)/products/detail/[id].tsx b/apps/admin-ui/app/(drawer)/dashboard/products/detail/[id].tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/products/detail/[id].tsx rename to apps/admin-ui/app/(drawer)/dashboard/products/detail/[id].tsx index 842b448..b394fc9 100644 --- a/apps/admin-ui/app/(drawer)/products/detail/[id].tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/products/detail/[id].tsx @@ -153,7 +153,7 @@ export default function ProductDetail() { const defaultSku = product?.skus?.[0] const handleEdit = () => { - router.push(`/products/edit?id=${productId}` as any); + router.push(`/(drawer)/dashboard/products/edit?id=${productId}` as any); }; diff --git a/apps/admin-ui/app/(drawer)/products/edit.tsx b/apps/admin-ui/app/(drawer)/dashboard/products/edit.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/products/edit.tsx rename to apps/admin-ui/app/(drawer)/dashboard/products/edit.tsx diff --git a/apps/admin-ui/app/(drawer)/products/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/products/index.tsx similarity index 97% rename from apps/admin-ui/app/(drawer)/products/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/products/index.tsx index a7125fd..32f485b 100644 --- a/apps/admin-ui/app/(drawer)/products/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/products/index.tsx @@ -52,11 +52,11 @@ export default function Products() { }, [products, searchTerm, activeFilter]); const handleEdit = (productId: number) => { - router.push(`/products/edit?id=${productId}` as any); + router.push(`/(drawer)/dashboard/products/edit?id=${productId}` as any); }; const handleViewDetails = (productId: number) => { - router.push(`/products/detail/${productId}` as any); + router.push(`/(drawer)/dashboard/products/detail/${productId}` as any); }; const FilterButton = ({ filter, label, count }: { filter: FilterType; label: string; count: number }) => ( @@ -105,7 +105,7 @@ export default function Products() { {/* Header */} Products - router.push('/products/add' as any)}> + router.push('/(drawer)/dashboard/products/add' as any)}> Add Product diff --git a/apps/admin-ui/app/(drawer)/rebalance-orders/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/rebalance-orders/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/rebalance-orders/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/rebalance-orders/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/rebalance-orders/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/rebalance-orders/index.tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/rebalance-orders/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/rebalance-orders/index.tsx index 848ed72..6508f39 100644 --- a/apps/admin-ui/app/(drawer)/rebalance-orders/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/rebalance-orders/index.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { View, TouchableOpacity, Alert, FlatList } from 'react-native'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { MyText, tw, MyTouchableOpacity, MyFlatList, BottomDialog } from 'common-ui'; -import { trpc } from '../../../src/trpc-client'; +import { trpc } from '../../../../src/trpc-client'; import dayjs from 'dayjs'; import { LinearGradient } from 'expo-linear-gradient'; diff --git a/apps/admin-ui/app/(drawer)/dashboard/send-notifications/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/send-notifications/_layout.tsx new file mode 100644 index 0000000..a9ed90c --- /dev/null +++ b/apps/admin-ui/app/(drawer)/dashboard/send-notifications/_layout.tsx @@ -0,0 +1,9 @@ +import { Stack } from 'expo-router' + +export default function Layout() { + return ( + + + + ) +} diff --git a/apps/admin-ui/app/(drawer)/send-notifications/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/send-notifications/index.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/send-notifications/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/send-notifications/index.tsx diff --git a/apps/admin-ui/app/(drawer)/slots/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/slots/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/slots/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/slots/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/slots/add.tsx b/apps/admin-ui/app/(drawer)/dashboard/slots/add.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/slots/add.tsx rename to apps/admin-ui/app/(drawer)/dashboard/slots/add.tsx diff --git a/apps/admin-ui/app/(drawer)/slots/edit/[id].tsx b/apps/admin-ui/app/(drawer)/dashboard/slots/edit/[id].tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/slots/edit/[id].tsx rename to apps/admin-ui/app/(drawer)/dashboard/slots/edit/[id].tsx diff --git a/apps/admin-ui/app/(drawer)/slots/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/slots/index.tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/slots/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/slots/index.tsx index 76bd7d5..ed6b6a0 100644 --- a/apps/admin-ui/app/(drawer)/slots/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/slots/index.tsx @@ -55,7 +55,7 @@ const SlotItemComponent: React.FC = ({ return ( router.push(`/(drawer)/slots/slot-details?slotId=${slot.id}`)} + onPress={() => router.push(`/(drawer)/dashboard/slots/slot-details?slotId=${slot.id}`)} activeOpacity={0.7} > diff --git a/apps/admin-ui/app/(drawer)/slots/slot-details.tsx b/apps/admin-ui/app/(drawer)/dashboard/slots/slot-details.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/slots/slot-details.tsx rename to apps/admin-ui/app/(drawer)/dashboard/slots/slot-details.tsx diff --git a/apps/admin-ui/app/(drawer)/stores/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/stores/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/stores/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/stores/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/stores/add.tsx b/apps/admin-ui/app/(drawer)/dashboard/stores/add.tsx similarity index 93% rename from apps/admin-ui/app/(drawer)/stores/add.tsx rename to apps/admin-ui/app/(drawer)/dashboard/stores/add.tsx index d4543cf..97b2da4 100644 --- a/apps/admin-ui/app/(drawer)/stores/add.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/stores/add.tsx @@ -18,7 +18,7 @@ export default function AddStore() { onSuccess: async (data) => { await refetchStores(); Alert.alert('Success', data.message); - router.push('/stores' as any); // Navigate back to stores list + router.push('/(drawer)/dashboard/stores' as any); // Navigate back to stores list }, onError: (error: any) => { Alert.alert('Error', error.message || 'Failed to create store'); diff --git a/apps/admin-ui/app/(drawer)/stores/edit.tsx b/apps/admin-ui/app/(drawer)/dashboard/stores/edit.tsx similarity index 97% rename from apps/admin-ui/app/(drawer)/stores/edit.tsx rename to apps/admin-ui/app/(drawer)/dashboard/stores/edit.tsx index 5fa365f..7f63fb3 100644 --- a/apps/admin-ui/app/(drawer)/stores/edit.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/stores/edit.tsx @@ -23,7 +23,7 @@ export default function EditStore() { onSuccess: (data) => { refetch(); Alert.alert('Success', data.message); - router.push('/stores' as any); + router.push('/(drawer)/dashboard/stores' as any); }, onError: (error: any) => { Alert.alert('Error', error.message || 'Failed to update store'); diff --git a/apps/admin-ui/app/(drawer)/stores/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/stores/index.tsx similarity index 98% rename from apps/admin-ui/app/(drawer)/stores/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/stores/index.tsx index 3110295..5bfabc5 100644 --- a/apps/admin-ui/app/(drawer)/stores/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/stores/index.tsx @@ -106,7 +106,7 @@ export default function Stores() { const stores = storesData?.stores || []; const handleEdit = (storeId: number) => { - router.push({ pathname: '/stores/edit', params: { id: storeId } }); + router.push({ pathname: '/(drawer)/dashboard/stores/edit', params: { id: storeId } }); }; const handleDelete = (storeId: number) => { @@ -207,7 +207,7 @@ export default function Stores() { router.push('/stores/add' as any)} + onPress={() => router.push('/(drawer)/dashboard/stores/add' as any)} > { - router.push(`/(drawer)/manage-orders/order-details/${orderId}`); + router.push(`/(drawer)/dashboard/manage-orders/order-details/${orderId}`); }, [router]); const handleSuspensionToggle = useCallback((isSuspended: boolean) => { diff --git a/apps/admin-ui/app/(drawer)/dashboard/user-management/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/user-management/_layout.tsx new file mode 100644 index 0000000..d04bd8e --- /dev/null +++ b/apps/admin-ui/app/(drawer)/dashboard/user-management/_layout.tsx @@ -0,0 +1,10 @@ +import { Stack } from 'expo-router' + +export default function Layout() { + return ( + + + + + ) +} diff --git a/apps/admin-ui/app/(drawer)/user-management/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/user-management/index.tsx similarity index 99% rename from apps/admin-ui/app/(drawer)/user-management/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/user-management/index.tsx index 52c4b78..65e1b43 100644 --- a/apps/admin-ui/app/(drawer)/user-management/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/user-management/index.tsx @@ -189,7 +189,7 @@ export default function UserManagement() { }, [hasNextPage, isFetchingNextPage, fetchNextPage]); const handleUserPress = useCallback((userId: number) => { - router.push(`/(drawer)/user-management/${userId}`); + router.push(`/(drawer)/dashboard/user-management/${userId}`); }, [router]); const renderUserItem = useCallback(({ item, index }: { item: User; index: number }) => { diff --git a/apps/admin-ui/app/(drawer)/vendor-snippets/_layout.tsx b/apps/admin-ui/app/(drawer)/dashboard/vendor-snippets/_layout.tsx similarity index 100% rename from apps/admin-ui/app/(drawer)/vendor-snippets/_layout.tsx rename to apps/admin-ui/app/(drawer)/dashboard/vendor-snippets/_layout.tsx diff --git a/apps/admin-ui/app/(drawer)/vendor-snippets/index.tsx b/apps/admin-ui/app/(drawer)/dashboard/vendor-snippets/index.tsx similarity index 96% rename from apps/admin-ui/app/(drawer)/vendor-snippets/index.tsx rename to apps/admin-ui/app/(drawer)/dashboard/vendor-snippets/index.tsx index 9c1ab52..9f3d290 100644 --- a/apps/admin-ui/app/(drawer)/vendor-snippets/index.tsx +++ b/apps/admin-ui/app/(drawer)/dashboard/vendor-snippets/index.tsx @@ -16,22 +16,22 @@ import { useMarkDataFetchers, MyTouchableOpacity, } from "common-ui"; -import { trpc, trpcClient } from "../../../src/trpc-client"; +import { trpc, trpcClient } from "../../../../src/trpc-client"; import MaterialIcons from "@expo/vector-icons/MaterialIcons"; import { Ionicons } from "@expo/vector-icons"; import dayjs from "dayjs"; import { LinearGradient } from "expo-linear-gradient"; import { useRouter } from "expo-router"; -import VendorSnippetForm from "../../../components/VendorSnippetForm"; -import SnippetOrdersView from "../../../components/SnippetOrdersView"; -import { SnippetMenu } from "../../../components/SnippetMenu"; -import { ProductListDialog } from "../../../components/ProductListDialog"; +import VendorSnippetForm from "../../../../components/VendorSnippetForm"; +import SnippetOrdersView from "../../../../components/SnippetOrdersView"; +import { SnippetMenu } from "../../../../components/SnippetMenu"; +import { ProductListDialog } from "../../../../components/ProductListDialog"; import { VendorSnippet, VendorSnippetProduct, VendorSnippetForm as VendorSnippetFormType, -} from "../../../types/vendor-snippets"; +} from "../../../../types/vendor-snippets"; const SnippetItem = ({ snippet, @@ -212,7 +212,7 @@ const SnippetItem = ({ router.push(`/(drawer)/slots/slot-details?slotId=${snippet.slotId}`)} + // onPress={() => router.push(`/(drawer)/dashboard/slots/slot-details?slotId=${snippet.slotId}`)} onPress={() => {}} activeOpacity={0.7} style={tw`flex-row items-center`} diff --git a/apps/admin-ui/app/(drawer)/users/index.tsx b/apps/admin-ui/app/(drawer)/users/index.tsx deleted file mode 100644 index 540acaf..0000000 --- a/apps/admin-ui/app/(drawer)/users/index.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React, { useState } from 'react'; -import { View, TouchableOpacity } from 'react-native'; -import { Image } from 'expo-image'; -import { useRouter } from 'expo-router'; -import { AppContainer, MyText, tw, MyFlatList, MyTextInput } from 'common-ui'; -import { trpc } from '@/src/trpc-client'; -import Ionicons from '@expo/vector-icons/Ionicons'; - -interface UserItemProps { - item: any; - onPress: (userId: string) => void; -} - -const UserItem: React.FC = ({ item, onPress }) => ( - onPress(item.id)} - > - {item.image ? ( - - ) : ( - - - - )} - - {item.name} - {item.email} - {item.mobile} - - -); - -export default function Users() { - const router = useRouter(); - const [search, setSearch] = useState(''); - - const { - data, - isLoading, - fetchNextPage, - hasNextPage, - refetch, - } = trpc.admin.staffUser.getUsers.useInfiniteQuery( - { search }, - { - getNextPageParam: (lastPage) => lastPage.nextCursor, - } - ); - - const users = data?.pages.flatMap(page => page.users) || []; - - const handleUserPress = (userId: string) => { - router.push(`/(drawer)/user-management/${userId}`); - }; - - return ( - - - - - - - } - keyExtractor={(item) => item.id.toString()} - onRefresh={refetch} - onEndReached={() => { - if (hasNextPage) { - fetchNextPage(); - } - }} - onEndReachedThreshold={0.5} - ListEmptyComponent={ - - No users found - - } - /> - - - ); -} \ No newline at end of file diff --git a/apps/admin-ui/services/notif-service/notif-context.tsx b/apps/admin-ui/services/notif-service/notif-context.tsx index 6998774..52ad74e 100755 --- a/apps/admin-ui/services/notif-service/notif-context.tsx +++ b/apps/admin-ui/services/notif-service/notif-context.tsx @@ -83,9 +83,9 @@ export const NotificationProvider: React.FC = ({ Notifications.addNotificationResponseReceivedListener((response) => { const data = response.notification.request.content.data; if (data && data.doctorId) { - router.push(`/(drawer)/dashboard`); + router.navigate(`/(drawer)/dashboard`); } else if (data && data.tokenId) { - router.push(`/(drawer)/dashboard`); + router.navigate(`/(drawer)/dashboard`); } }); diff --git a/apps/admin-ui/src/components/CouponForm.tsx b/apps/admin-ui/src/components/CouponForm.tsx index 9251c54..020f922 100644 --- a/apps/admin-ui/src/components/CouponForm.tsx +++ b/apps/admin-ui/src/components/CouponForm.tsx @@ -9,10 +9,16 @@ import { CreateCouponPayload } from 'common-ui/shared-types'; const USERS_PAGE_SIZE = 10; +interface CouponFormValues extends CreateCouponPayload { + isReservedCoupon?: boolean; + couponCodes?: string[]; + skuIds?: number[]; +} + interface CouponFormProps { - onSubmit: (values: CreateCouponPayload & { isReservedCoupon?: boolean }) => void; + onSubmit: (values: CouponFormValues) => void; isLoading: boolean; - initialValues?: Partial; + initialValues?: Partial; } const couponValidationSchema = Yup.object().shape({ @@ -22,6 +28,13 @@ const couponValidationSchema = Yup.object().shape({ .min(3, 'Coupon code must be at least 3 characters') .max(50, 'Coupon code cannot exceed 50 characters') .matches(/^[A-Z0-9_-]+$/, 'Coupon code can only contain uppercase letters, numbers, underscores, and hyphens'), + couponCodes: Yup.array().of( + Yup.string() + .required('Code is required') + .min(3, 'Code must be at least 3 characters') + .max(50, 'Code cannot exceed 50 characters') + .matches(/^[A-Z0-9_-]+$/, 'Code can only contain uppercase letters, numbers, underscores, and hyphens') + ), discountPercent: Yup.number() .min(0, 'Must be positive') .max(100, 'Cannot exceed 100%') @@ -49,6 +62,22 @@ const couponValidationSchema = Yup.object().shape({ return this.createError({ message: 'Must provide either percentage or flat discount' }); } return true; +}).test('reserved-codes-required', 'At least one coupon code is required', function(value: any) { + if (value.isReservedCoupon) { + const codes = (value.couponCodes || []).filter((c: string) => c && c.trim()); + if (codes.length === 0) { + return this.createError({ path: 'couponCodes', message: 'Add at least one coupon code' }); + } + } + return true; +}).test('reserved-codes-unique', 'Coupon codes must be unique', function(value: any) { + if (value.isReservedCoupon) { + const codes = (value.couponCodes || []).map((c: string) => c.trim()).filter(Boolean); + if (new Set(codes).size !== codes.length) { + return this.createError({ path: 'couponCodes', message: 'Coupon codes must be unique' }); + } + } + return true; }); export default function CouponForm({ onSubmit, isLoading, initialValues }: CouponFormProps) { @@ -94,8 +123,9 @@ export default function CouponForm({ onSubmit, isLoading, initialValues }: Coupo // User search functionality will be inside Formik - const defaultValues: CreateCouponPayload & { isReservedCoupon?: boolean } = { + const defaultValues: CouponFormValues = { couponCode: '', + couponCodes: [], isUserBased: false, isApplyForAll: false, targetUsers: [], @@ -113,8 +143,8 @@ export default function CouponForm({ onSubmit, isLoading, initialValues }: Coupo }; return ( - + initialValues={(initialValues || defaultValues) as CouponFormValues} validationSchema={couponValidationSchema} onSubmit={onSubmit} > @@ -143,18 +173,70 @@ export default function CouponForm({ onSubmit, isLoading, initialValues }: Coupo Is Reserved Coupon - {/* Coupon Code */} - - setFieldValue('couponCode', text.toUpperCase())} - keyboardType="default" - autoCapitalize="characters" - error={!!(touched.couponCode && errors.couponCode)} - /> - + {/* Coupon Code (single, non-reserved) OR Coupon Codes (array, reserved) */} + {!isReserved ? ( + + setFieldValue('couponCode', text.toUpperCase())} + keyboardType="default" + autoCapitalize="characters" + error={!!(touched.couponCode && errors.couponCode)} + /> + + ) : ( + + Coupon Codes + + Each code creates a separate reserved coupon with the same settings. + + {(values.couponCodes || []).map((code: string, index: number) => { + const codeError = Array.isArray(errors.couponCodes) + ? (errors.couponCodes as any)[index] + : errors.couponCodes; + return ( + + + { + const next = [...(values.couponCodes || [])]; + next[index] = text.toUpperCase(); + setFieldValue('couponCodes', next); + }} + keyboardType="default" + autoCapitalize="characters" + error={!!codeError} + /> + {codeError && {codeError}} + + { + const next = (values.couponCodes || []).filter((_: string, i: number) => i !== index); + setFieldValue('couponCodes', next); + }} + style={tw`ml-2 p-2`} + > + + + + ); + })} + {(errors.couponCodes as any)?.message && ( + {(errors.couponCodes as any).message} + )} + setFieldValue('couponCodes', [...(values.couponCodes || []), ''])} + style={tw`mt-2 py-2 px-3 bg-blue-50 rounded-lg border border-blue-200 self-start`} + > + + Add Code + + + )} {/* Discount Type Selection */}