From 86de06078ffc5ddf00b0c179b7cf39a2cdec69d4 Mon Sep 17 00:00:00 2001 From: shafi54 <108669266+shafi-aviz@users.noreply.github.com> Date: Sun, 1 Feb 2026 21:01:05 +0530 Subject: [PATCH] enh --- apps/admin-ui/app/(drawer)/add-slot/index.tsx | 29 +- apps/admin-ui/app/(drawer)/slots/index.tsx | 40 +- apps/admin-ui/components/SlotForm.tsx | 36 +- apps/backend/drizzle/0070_known_ares.sql | 1 + apps/backend/drizzle/meta/0070_snapshot.json | 3624 +++++++++++++++++ apps/backend/drizzle/meta/_journal.json | 7 + apps/backend/src/db/schema.ts | 1 + apps/backend/src/trpc/admin-apis/slots.ts | 21 +- .../src/components/3d/Characters.tsx | 26 +- 9 files changed, 3749 insertions(+), 36 deletions(-) create mode 100644 apps/backend/drizzle/0070_known_ares.sql create mode 100644 apps/backend/drizzle/meta/0070_snapshot.json diff --git a/apps/admin-ui/app/(drawer)/add-slot/index.tsx b/apps/admin-ui/app/(drawer)/add-slot/index.tsx index 5ee2002..ac69049 100644 --- a/apps/admin-ui/app/(drawer)/add-slot/index.tsx +++ b/apps/admin-ui/app/(drawer)/add-slot/index.tsx @@ -1,22 +1,43 @@ import React from 'react'; -import { View } from 'react-native'; +import { View, Text } from 'react-native'; import { AppContainer } from 'common-ui'; import SlotForm from '../../../components/SlotForm'; -import { useRouter } from 'expo-router'; +import { useRouter, useLocalSearchParams } from 'expo-router'; import { trpc } from '../../../src/trpc-client'; export default function AddSlot() { const router = useRouter(); + const { baseslot } = useLocalSearchParams(); + const baseSlotId = baseslot ? parseInt(baseslot as string) : null; + const { refetch } = trpc.admin.slots.getAll.useQuery(); + const { data: baseSlotData, isLoading } = trpc.admin.slots.getSlotById.useQuery( + { id: baseSlotId! }, + { enabled: !!baseSlotId } + ); const handleSlotAdded = () => { refetch(); router.back(); }; + if (isLoading && baseSlotId) { + return ( + + + Loading base slot... + + + ); + } + return ( - + p.id) || []} + initialGroupIds={baseSlotData?.slot?.groupIds || []} + /> ); -} \ No newline at end of file +} diff --git a/apps/admin-ui/app/(drawer)/slots/index.tsx b/apps/admin-ui/app/(drawer)/slots/index.tsx index 139161c..a46ad63 100644 --- a/apps/admin-ui/app/(drawer)/slots/index.tsx +++ b/apps/admin-ui/app/(drawer)/slots/index.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; -import { MaterialCommunityIcons } from '@expo/vector-icons'; -import { View, TouchableOpacity, FlatList } from 'react-native'; +import { MaterialCommunityIcons, Entypo } from '@expo/vector-icons'; +import { View, TouchableOpacity, FlatList, Alert } from 'react-native'; import { AppContainer, MyText, tw, MyFlatList , BottomDialog, MyTouchableOpacity } from 'common-ui'; import { trpc } from '../../../src/trpc-client'; import { useRouter } from 'expo-router'; @@ -20,6 +20,7 @@ const SlotItemComponent: React.FC = ({ setDialogProducts, setDialogOpen, }) => { + const [menuOpen, setMenuOpen] = useState(false); const slotProducts = slot.products?.map((p: any) => p.name).filter(Boolean) || []; const displayProducts = slotProducts.slice(0, 2).join(', '); @@ -57,9 +58,44 @@ const SlotItemComponent: React.FC = ({ {statusText} + setMenuOpen(true)} + style={tw`ml-2 p-1`} + hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }} + > + + + {/* Replicate Menu Dialog */} + setMenuOpen(false)}> + + Slot #{slot.id} Actions + { + setMenuOpen(false); + router.push(`/add-slot?baseslot=${slot.id}` as any); + }} + style={tw`py-4 border-b border-gray-200`} + > + + + Replicate Slot + + + setMenuOpen(false)} + style={tw`py-4 mt-2`} + > + + + Cancel + + + + + {/* Divider */} diff --git a/apps/admin-ui/components/SlotForm.tsx b/apps/admin-ui/components/SlotForm.tsx index c3880b7..e7fda24 100644 --- a/apps/admin-ui/components/SlotForm.tsx +++ b/apps/admin-ui/components/SlotForm.tsx @@ -20,6 +20,7 @@ interface SlotFormProps { initialIsActive?: boolean; slotId?: number; initialProductIds?: number[]; + initialGroupIds?: number[]; } export default function SlotForm({ @@ -29,13 +30,26 @@ export default function SlotForm({ initialIsActive = true, slotId, initialProductIds = [], + initialGroupIds = [], }: SlotFormProps) { + const { data: slotData } = trpc.admin.slots.getSlotById.useQuery( + { id: slotId! }, + { enabled: !!slotId } + ); + + const vendorSnippetsFromSlot = (slotData?.slot?.vendorSnippets || []).map((snippet: any) => ({ + name: snippet.name || '', + groupIds: snippet.groupIds || [], + productIds: snippet.productIds || [], + validTill: snippet.validTill || undefined, + })) as VendorSnippet[]; + const initialValues = { - deliveryTime: initialDeliveryTime || null, - freezeTime: initialFreezeTime || null, - selectedGroupIds: [] as number[], - selectedProductIds: initialProductIds, - vendorSnippetList: [] as VendorSnippet[], + deliveryTime: initialDeliveryTime || (slotData?.slot?.deliveryTime ? new Date(slotData.slot.deliveryTime) : null), + freezeTime: initialFreezeTime || (slotData?.slot?.freezeTime ? new Date(slotData.slot.freezeTime) : null), + selectedGroupIds: initialGroupIds.length > 0 ? initialGroupIds : (slotData?.slot?.groupIds || []), + selectedProductIds: initialProductIds.length > 0 ? initialProductIds : (slotData?.slot?.products?.map((p: any) => p.id) || []), + vendorSnippetList: vendorSnippetsFromSlot, }; const { mutate: createSlot, isPending: isCreating } = trpc.admin.slots.createSlot.useMutation(); @@ -63,20 +77,14 @@ export default function SlotForm({ deliveryTime: values.deliveryTime.toISOString(), freezeTime: values.freezeTime.toISOString(), isActive: initialIsActive, + groupIds: values.selectedGroupIds, productIds: values.selectedProductIds, - vendorSnippets: values.vendorSnippetList.map(snippet => ({ + vendorSnippets: values.vendorSnippetList.map((snippet: VendorSnippet) => ({ name: snippet.name, productIds: snippet.productIds, validTill: snippet.validTill, })), }; - - console.log({snippetList: values.vendorSnippetList}) - - values.vendorSnippetList.forEach((snippet, index) => { - console.log({snippet}) - - }); if (isEditMode && slotId) { @@ -160,7 +168,7 @@ export default function SlotForm({ {({ push, remove }) => ( Vendor Snippets - {values.vendorSnippetList.map((snippet, index) => ( + {values.vendorSnippetList.map((snippet: VendorSnippet, index: number) => ( = 1 AND \"mf\".\"product_reviews\".\"ratings\" <= 5" + } + }, + "isRLSEnabled": false + }, + "mf.product_slots": { + "name": "product_slots", + "schema": "mf", + "columns": { + "product_id": { + "name": "product_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "slot_id": { + "name": "slot_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "product_slots_product_id_product_info_id_fk": { + "name": "product_slots_product_id_product_info_id_fk", + "tableFrom": "product_slots", + "tableTo": "product_info", + "schemaTo": "mf", + "columnsFrom": [ + "product_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "product_slots_slot_id_delivery_slot_info_id_fk": { + "name": "product_slots_slot_id_delivery_slot_info_id_fk", + "tableFrom": "product_slots", + "tableTo": "delivery_slot_info", + "schemaTo": "mf", + "columnsFrom": [ + "slot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "product_slot_pk": { + "name": "product_slot_pk", + "nullsNotDistinct": false, + "columns": [ + "product_id", + "slot_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.product_tag_info": { + "name": "product_tag_info", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "product_tag_info_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "tag_name": { + "name": "tag_name", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true + }, + "tag_description": { + "name": "tag_description", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "image_url": { + "name": "image_url", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "is_dashboard_tag": { + "name": "is_dashboard_tag", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "product_tag_info_tag_name_unique": { + "name": "product_tag_info_tag_name_unique", + "nullsNotDistinct": false, + "columns": [ + "tag_name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.product_tags": { + "name": "product_tags", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "product_tags_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "product_id": { + "name": "product_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tag_id": { + "name": "tag_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "assigned_at": { + "name": "assigned_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "product_tags_product_id_product_info_id_fk": { + "name": "product_tags_product_id_product_info_id_fk", + "tableFrom": "product_tags", + "tableTo": "product_info", + "schemaTo": "mf", + "columnsFrom": [ + "product_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "product_tags_tag_id_product_tag_info_id_fk": { + "name": "product_tags_tag_id_product_tag_info_id_fk", + "tableFrom": "product_tags", + "tableTo": "product_tag_info", + "schemaTo": "mf", + "columnsFrom": [ + "tag_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_product_tag": { + "name": "unique_product_tag", + "nullsNotDistinct": false, + "columns": [ + "product_id", + "tag_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.refunds": { + "name": "refunds", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "refunds_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "order_id": { + "name": "order_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "refund_amount": { + "name": "refund_amount", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": false + }, + "refund_status": { + "name": "refund_status", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false, + "default": "'none'" + }, + "merchant_refund_id": { + "name": "merchant_refund_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "refund_processed_at": { + "name": "refund_processed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "refunds_order_id_orders_id_fk": { + "name": "refunds_order_id_orders_id_fk", + "tableFrom": "refunds", + "tableTo": "orders", + "schemaTo": "mf", + "columnsFrom": [ + "order_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.reserved_coupons": { + "name": "reserved_coupons", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "reserved_coupons_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "secret_code": { + "name": "secret_code", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true + }, + "coupon_code": { + "name": "coupon_code", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true + }, + "discount_percent": { + "name": "discount_percent", + "type": "numeric(5, 2)", + "primaryKey": false, + "notNull": false + }, + "flat_discount": { + "name": "flat_discount", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": false + }, + "min_order": { + "name": "min_order", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": false + }, + "product_ids": { + "name": "product_ids", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "max_value": { + "name": "max_value", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": false + }, + "valid_till": { + "name": "valid_till", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "max_limit_for_user": { + "name": "max_limit_for_user", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "exclusive_apply": { + "name": "exclusive_apply", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_redeemed": { + "name": "is_redeemed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "redeemed_by": { + "name": "redeemed_by", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "redeemed_at": { + "name": "redeemed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "reserved_coupons_redeemed_by_users_id_fk": { + "name": "reserved_coupons_redeemed_by_users_id_fk", + "tableFrom": "reserved_coupons", + "tableTo": "users", + "schemaTo": "mf", + "columnsFrom": [ + "redeemed_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "reserved_coupons_created_by_staff_users_id_fk": { + "name": "reserved_coupons_created_by_staff_users_id_fk", + "tableFrom": "reserved_coupons", + "tableTo": "staff_users", + "schemaTo": "mf", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "reserved_coupons_secret_code_unique": { + "name": "reserved_coupons_secret_code_unique", + "nullsNotDistinct": false, + "columns": [ + "secret_code" + ] + }, + "unique_secret_code": { + "name": "unique_secret_code", + "nullsNotDistinct": false, + "columns": [ + "secret_code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.special_deals": { + "name": "special_deals", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "special_deals_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "product_id": { + "name": "product_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true + }, + "price": { + "name": "price", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true + }, + "valid_till": { + "name": "valid_till", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "special_deals_product_id_product_info_id_fk": { + "name": "special_deals_product_id_product_info_id_fk", + "tableFrom": "special_deals", + "tableTo": "product_info", + "schemaTo": "mf", + "columnsFrom": [ + "product_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.staff_permissions": { + "name": "staff_permissions", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "staff_permissions_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "permission_name": { + "name": "permission_name", + "type": "staff_permission", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_permission_name": { + "name": "unique_permission_name", + "nullsNotDistinct": false, + "columns": [ + "permission_name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.staff_role_permissions": { + "name": "staff_role_permissions", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "staff_role_permissions_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "staff_role_id": { + "name": "staff_role_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "staff_permission_id": { + "name": "staff_permission_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "staff_role_permissions_staff_role_id_staff_roles_id_fk": { + "name": "staff_role_permissions_staff_role_id_staff_roles_id_fk", + "tableFrom": "staff_role_permissions", + "tableTo": "staff_roles", + "schemaTo": "mf", + "columnsFrom": [ + "staff_role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "staff_role_permissions_staff_permission_id_staff_permissions_id_fk": { + "name": "staff_role_permissions_staff_permission_id_staff_permissions_id_fk", + "tableFrom": "staff_role_permissions", + "tableTo": "staff_permissions", + "schemaTo": "mf", + "columnsFrom": [ + "staff_permission_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_role_permission": { + "name": "unique_role_permission", + "nullsNotDistinct": false, + "columns": [ + "staff_role_id", + "staff_permission_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.staff_roles": { + "name": "staff_roles", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "staff_roles_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "role_name": { + "name": "role_name", + "type": "staff_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_role_name": { + "name": "unique_role_name", + "nullsNotDistinct": false, + "columns": [ + "role_name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.staff_users": { + "name": "staff_users", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "staff_users_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "staff_role_id": { + "name": "staff_role_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "staff_users_staff_role_id_staff_roles_id_fk": { + "name": "staff_users_staff_role_id_staff_roles_id_fk", + "tableFrom": "staff_users", + "tableTo": "staff_roles", + "schemaTo": "mf", + "columnsFrom": [ + "staff_role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.store_info": { + "name": "store_info", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "store_info_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "image_url": { + "name": "image_url", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "owner": { + "name": "owner", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "store_info_owner_staff_users_id_fk": { + "name": "store_info_owner_staff_users_id_fk", + "tableFrom": "store_info", + "tableTo": "staff_users", + "schemaTo": "mf", + "columnsFrom": [ + "owner" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.units": { + "name": "units", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "units_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "short_notation": { + "name": "short_notation", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true + }, + "full_name": { + "name": "full_name", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_short_notation": { + "name": "unique_short_notation", + "nullsNotDistinct": false, + "columns": [ + "short_notation" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.upload_url_status": { + "name": "upload_url_status", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "upload_url_status_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "key": { + "name": "key", + "type": "varchar(500)", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "upload_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.user_creds": { + "name": "user_creds", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "user_creds_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_password": { + "name": "user_password", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_creds_user_id_users_id_fk": { + "name": "user_creds_user_id_users_id_fk", + "tableFrom": "user_creds", + "tableTo": "users", + "schemaTo": "mf", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.user_details": { + "name": "user_details", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "user_details_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "bio": { + "name": "bio", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "date_of_birth": { + "name": "date_of_birth", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "gender": { + "name": "gender", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "occupation": { + "name": "occupation", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "profile_image": { + "name": "profile_image", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "is_suspended": { + "name": "is_suspended", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_details_user_id_users_id_fk": { + "name": "user_details_user_id_users_id_fk", + "tableFrom": "user_details", + "tableTo": "users", + "schemaTo": "mf", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_details_user_id_unique": { + "name": "user_details_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.users": { + "name": "users", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "users_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "mobile": { + "name": "mobile", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_email": { + "name": "unique_email", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "mf.vendor_snippets": { + "name": "vendor_snippets", + "schema": "mf", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "vendor_snippets_id_seq", + "schema": "mf", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "snippet_code": { + "name": "snippet_code", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "slot_id": { + "name": "slot_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "is_permanent": { + "name": "is_permanent", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "product_ids": { + "name": "product_ids", + "type": "integer[]", + "primaryKey": false, + "notNull": true + }, + "valid_till": { + "name": "valid_till", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "vendor_snippets_slot_id_delivery_slot_info_id_fk": { + "name": "vendor_snippets_slot_id_delivery_slot_info_id_fk", + "tableFrom": "vendor_snippets", + "tableTo": "delivery_slot_info", + "schemaTo": "mf", + "columnsFrom": [ + "slot_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "vendor_snippets_snippet_code_unique": { + "name": "vendor_snippets_snippet_code_unique", + "nullsNotDistinct": false, + "columns": [ + "snippet_code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.payment_status": { + "name": "payment_status", + "schema": "public", + "values": [ + "pending", + "success", + "cod", + "failed" + ] + }, + "public.staff_permission": { + "name": "staff_permission", + "schema": "public", + "values": [ + "crud_product", + "make_coupon", + "crud_staff_users" + ] + }, + "public.staff_role": { + "name": "staff_role", + "schema": "public", + "values": [ + "super_admin", + "admin", + "marketer", + "delivery_staff" + ] + }, + "public.upload_status": { + "name": "upload_status", + "schema": "public", + "values": [ + "pending", + "claimed" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/backend/drizzle/meta/_journal.json b/apps/backend/drizzle/meta/_journal.json index 18e947c..6dbc0d1 100644 --- a/apps/backend/drizzle/meta/_journal.json +++ b/apps/backend/drizzle/meta/_journal.json @@ -491,6 +491,13 @@ "when": 1769718702463, "tag": "0069_violet_smiling_tiger", "breakpoints": true + }, + { + "idx": 70, + "version": "7", + "when": 1769958949864, + "tag": "0070_known_ares", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/backend/src/db/schema.ts b/apps/backend/src/db/schema.ts index ed63934..4e92e55 100755 --- a/apps/backend/src/db/schema.ts +++ b/apps/backend/src/db/schema.ts @@ -192,6 +192,7 @@ export const deliverySlotInfo = mf.table('delivery_slot_info', { isActive: boolean('is_active').notNull().default(true), isFlash: boolean('is_flash').notNull().default(false), deliverySequence: jsonb('delivery_sequence').$defaultFn(() => {}), + groupIds: jsonb('group_ids').$defaultFn(() => []), }); export const vendorSnippets = mf.table('vendor_snippets', { diff --git a/apps/backend/src/trpc/admin-apis/slots.ts b/apps/backend/src/trpc/admin-apis/slots.ts index 5ed73d0..6cb020c 100644 --- a/apps/backend/src/trpc/admin-apis/slots.ts +++ b/apps/backend/src/trpc/admin-apis/slots.ts @@ -2,7 +2,7 @@ import { router, protectedProcedure } from "../trpc-index"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { db } from "../../db/db_index"; -import { deliverySlotInfo, productSlots, productInfo, vendorSnippets } from "../../db/schema"; +import { deliverySlotInfo, productSlots, productInfo, vendorSnippets, productGroupInfo } from "../../db/schema"; import { eq, inArray, and, desc } from "drizzle-orm"; import { ApiError } from "../../lib/api-error"; import { appUrl } from "../../lib/env-exporter"; @@ -26,6 +26,7 @@ const createSlotSchema = z.object({ productIds: z.array(z.number().int().positive()).min(1), validTill: z.string().optional(), })).optional(), + groupIds: z.array(z.number()).optional(), }); const getSlotByIdSchema = z.object({ @@ -43,6 +44,7 @@ const updateSlotSchema = z.object({ productIds: z.array(z.number().int().positive()).min(1), validTill: z.string().optional(), })).optional(), + groupIds: z.array(z.number()).optional(), }); const deleteSlotSchema = z.object({ @@ -229,7 +231,7 @@ export const slotsRouter = router({ throw new TRPCError({ code: "UNAUTHORIZED", message: "Access denied" }); } - const { deliveryTime, freezeTime, isActive, productIds, vendorSnippets: snippets } = input; + const { deliveryTime, freezeTime, isActive, productIds, vendorSnippets: snippets, groupIds } = input; // Validate required fields if (!deliveryTime || !freezeTime) { @@ -244,6 +246,7 @@ export const slotsRouter = router({ deliveryTime: new Date(deliveryTime), freezeTime: new Date(freezeTime), isActive: isActive !== undefined ? isActive : true, + groupIds: groupIds !== undefined ? groupIds : [], }) .returning(); @@ -348,6 +351,7 @@ export const slotsRouter = router({ slot: { ...slot, deliverySequence: slot.deliverySequence as number[], + groupIds: slot.groupIds as number[], products: slot.productSlots.map((ps) => ps.product), vendorSnippets: slot.vendorSnippets?.map(snippet => ({ ...snippet, @@ -364,12 +368,22 @@ export const slotsRouter = router({ throw new TRPCError({ code: "UNAUTHORIZED", message: "Access denied" }); } try{ - const { id, deliveryTime, freezeTime, isActive, productIds, vendorSnippets: snippets } = input; + const { id, deliveryTime, freezeTime, isActive, productIds, vendorSnippets: snippets, groupIds } = input; if (!deliveryTime || !freezeTime) { throw new ApiError("Delivery time and orders close time are required", 400); } + // Filter groupIds to only include valid (existing) groups + let validGroupIds = groupIds; + if (groupIds && groupIds.length > 0) { + const existingGroups = await db.query.productGroupInfo.findMany({ + where: inArray(productGroupInfo.id, groupIds), + columns: { id: true }, + }); + validGroupIds = existingGroups.map(g => g.id); + } + return await db.transaction(async (tx) => { const [updatedSlot] = await tx .update(deliverySlotInfo) @@ -377,6 +391,7 @@ export const slotsRouter = router({ deliveryTime: new Date(deliveryTime), freezeTime: new Date(freezeTime), isActive: isActive !== undefined ? isActive : true, + groupIds: validGroupIds !== undefined ? validGroupIds : [], }) .where(eq(deliverySlotInfo.id, id)) .returning(); diff --git a/apps/fallback-ui/src/components/3d/Characters.tsx b/apps/fallback-ui/src/components/3d/Characters.tsx index 6d88971..0b919a1 100644 --- a/apps/fallback-ui/src/components/3d/Characters.tsx +++ b/apps/fallback-ui/src/components/3d/Characters.tsx @@ -54,7 +54,7 @@ function AnimatedFlag({ flagTexture, isCelebrating, time }: { flagTexture: THREE // Increase segmentation for better cloth simulation geometry.dispose(); - const newGeometry = new THREE.PlaneGeometry(1.5, 0.75, 24, 12); + const newGeometry = new THREE.PlaneGeometry(2.5, 1.25, 32, 16); flagMeshRef.current.geometry = newGeometry; originalPositions.current = new Float32Array(newGeometry.attributes.position.array); } @@ -77,15 +77,15 @@ function AnimatedFlag({ flagTexture, isCelebrating, time }: { flagTexture: THREE const y = originalPos[i + 1]; const z = originalPos[i + 2]; - // Distance from flag pole - const distanceFromPole = (x + 0.75) / 1.5; + // Distance from flag pole (adjusted for larger flag width of 2.5) + const distanceFromPole = (x + 1.25) / 2.5; // Multiple wave layers const wave1 = Math.sin(elapsed * flutterSpeed * 0.5 + distanceFromPole * 4) * 0.15 * distanceFromPole * windStrength; const wave2 = Math.sin(elapsed * flutterSpeed + distanceFromPole * 8 + y * 3) * 0.08 * distanceFromPole * windStrength; const wave3 = Math.sin(elapsed * flutterSpeed * 2 + distanceFromPole * 12 + y * 5) * 0.04 * distanceFromPole * windStrength; const turbulence = noise(elapsed * 2 + distanceFromPole * 6) * 0.06 * distanceFromPole * windStrength; - const verticalFlutter = Math.sin(elapsed * flutterSpeed * 0.7 + distanceFromPole * 3) * 0.05 * (1 - Math.abs(y) / 0.375) * distanceFromPole; + const verticalFlutter = Math.sin(elapsed * flutterSpeed * 0.7 + distanceFromPole * 3) * 0.05 * (1 - Math.abs(y) / 0.625) * distanceFromPole; const zOffset = (wave1 + wave2 + wave3 + turbulence) * (0.3 + distanceFromPole * 0.7); const yOffset = verticalFlutter * windStrength; @@ -103,8 +103,8 @@ function AnimatedFlag({ flagTexture, isCelebrating, time }: { flagTexture: THREE }); return ( - - + +