add sales visits ui

This commit is contained in:
2026-08-31 13:00:33 +05:30
parent 5c4e1b590a
commit da9caa855a
11 changed files with 518 additions and 3 deletions
@@ -0,0 +1,69 @@
'use client'
import { useEffect, useState } from 'react'
import { Badge } from '@/components/ui/badge'
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
} from '@/components/ui/dialog'
import { toast } from '@/components/ui/toast'
import { stores as storesApi } from '@/lib/api/index'
import type { StoreResponse, StoreVisitHistoryItem } from '@/types/api'
interface StoreVisitHistorySheetProps {
open: boolean
onClose: () => void
store: StoreResponse | null
}
export function StoreVisitHistorySheet({ open, onClose, store }: StoreVisitHistorySheetProps) {
const [visits, setVisits] = useState<StoreVisitHistoryItem[] | null>(null)
useEffect(() => {
if (!open || !store) return
setVisits(null)
storesApi.visitHistory(store.id)
.then(setVisits)
.catch(() => toast.add({ title: 'Failed to load visit history', type: 'error' }))
}, [open, store])
if (!store) return null
return (
<Dialog open={open} onOpenChange={(v) => !v && onClose()}>
<DialogContent className="overflow-y-auto sm:max-w-lg">
<DialogHeader>
<DialogTitle>Visit History — {store.storeName}</DialogTitle>
<DialogDescription>
Check-ins and check-outs logged against this store.
</DialogDescription>
</DialogHeader>
{visits === null ? (
<p className="text-sm text-muted-foreground">Loading…</p>
) : visits.length === 0 ? (
<p className="text-sm text-muted-foreground">No visits logged yet.</p>
) : (
<ul className="flex flex-col gap-2">
{visits.map((v) => (
<li key={v.visitId} className="flex items-center justify-between rounded-md border p-2 text-sm">
<span>
{new Date(v.visitDate).toLocaleString('en-GB', {
day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit',
})}
</span>
<Badge variant={v.outcome === 'Completed' ? 'default' : 'secondary'}>
{v.outcome}
</Badge>
</li>
))}
</ul>
)}
</DialogContent>
</Dialog>
)
}
@@ -13,6 +13,7 @@ import { stores as storesApi, getApiError, getPaginatedItems } from '@/lib/api/i
import type { StoreResponse, KycStatus } from '@/types/api'
import { StoreSheet } from './store-sheet'
import { StoreVisitHistorySheet } from './store-visit-history-sheet'
function kycBadgeVariant(status: KycStatus): 'default' | 'secondary' | 'destructive' {
if (status === 'Verified') return 'default'
@@ -29,6 +30,8 @@ export function StoresClient() {
const [sheetOpen, setSheetOpen] = useState(false)
const [editing, setEditing] = useState<StoreResponse | null>(null)
const [historyOpen, setHistoryOpen] = useState(false)
const [viewingHistory, setViewingHistory] = useState<StoreResponse | null>(null)
const fetchData = useCallback(async (p: number, ps: number) => {
setLoading(true)
@@ -57,6 +60,11 @@ export function StoresClient() {
setSheetOpen(true)
}
function openHistory(store: StoreResponse) {
setViewingHistory(store)
setHistoryOpen(true)
}
async function toggleActive(store: StoreResponse) {
try {
await storesApi.update(store.id, { isActive: !store.isActive })
@@ -125,6 +133,11 @@ export function StoresClient() {
label: 'Edit store',
onClick: openEdit,
},
{
action: 'confirm',
label: 'View visit history',
onClick: openHistory,
},
{
action: 'deactivate',
label: 'Deactivate store',
@@ -139,7 +152,7 @@ export function StoresClient() {
},
],
},
}), [pageSize, openEdit, toggleActive])
}), [pageSize, openEdit, openHistory, toggleActive])
return (
<>
@@ -173,6 +186,12 @@ export function StoresClient() {
store={editing}
onSuccess={() => fetchData(page, pageSize)}
/>
<StoreVisitHistorySheet
open={historyOpen}
onClose={() => setHistoryOpen(false)}
store={viewingHistory}
/>
</>
)
}