Files
dmenu-admin/src/pages/orders/components/CreateOrderItemsSection.tsx
T
hamid zarghami 3c6d3f009a
deploy to danak / build_and_deploy (push) Has been cancelled
create order without scoll
2026-07-01 10:10:15 +03:30

152 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { type FC, useMemo, useState } from 'react'
import type { FormikProps } from 'formik'
import { Add } from 'iconsax-react'
import Input from '@/components/Input'
import type { Food } from '@/pages/food/types/Types'
import { formatPrice } from '@/helpers/func'
import { getFoodUnitPrice } from '../hooks/useCreateOrderForm'
import type { CreateOrderFormValues } from '../hooks/useCreateOrderForm'
interface CreateOrderItemsSectionProps {
formik: FormikProps<CreateOrderFormValues>
foods: Food[]
onAddFood: (foodId: string) => void
}
const CreateOrderItemsSection: FC<CreateOrderItemsSectionProps> = ({
formik,
foods,
onAddFood,
}) => {
const [search, setSearch] = useState('')
const [selectedCategoryId, setSelectedCategoryId] = useState<string | null>(null)
const categories = useMemo(() => {
const categoryMap = new Map<string, string>()
foods.forEach((food) => {
if (food.category?.id) {
categoryMap.set(food.category.id, food.category.title)
}
})
return Array.from(categoryMap.entries())
.map(([id, title]) => ({ id, title }))
.sort((a, b) => a.title.localeCompare(b.title, 'fa'))
}, [foods])
const filteredFoods = useMemo(() => {
let result = foods
if (selectedCategoryId) {
result = result.filter((food) => food.category?.id === selectedCategoryId)
}
const query = search.trim().toLowerCase()
if (query) {
result = result.filter((food) => food.title.toLowerCase().includes(query))
}
return result
}, [foods, search, selectedCategoryId])
return (
<div className='w-full h-full bg-white rounded-4xl p-5 flex flex-col min-h-0'>
<div className='text-sm font-light flex-shrink-0'>انتخاب غذا</div>
<div className='mt-3 flex-1 min-h-0 flex flex-col border border-border rounded-xl p-3'>
<Input
variant='search'
className='bg-[#EEF0F7]'
placeholder='جستجوی غذا...'
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
{categories.length > 0 && (
<div className='mt-2 flex gap-1.5 overflow-x-auto flex-shrink-0 pb-0.5'>
<button
type='button'
onClick={() => setSelectedCategoryId(null)}
className={`flex-shrink-0 px-2.5 h-7 rounded-full text-[11px] transition-colors ${
selectedCategoryId === null
? 'bg-primary text-white'
: 'bg-[#EEF0F7] text-description hover:bg-[#E4E7F0]'
}`}
>
همه
</button>
{categories.map((category) => (
<button
key={category.id}
type='button'
onClick={() => setSelectedCategoryId(category.id)}
className={`flex-shrink-0 px-2.5 h-7 rounded-full text-[11px] transition-colors whitespace-nowrap ${
selectedCategoryId === category.id
? 'bg-primary text-white'
: 'bg-[#EEF0F7] text-description hover:bg-[#E4E7F0]'
}`}
>
{category.title}
</button>
))}
</div>
)}
<div className='mt-2 flex-1 min-h-0 overflow-y-auto space-y-1'>
{filteredFoods.length === 0 ? (
<div className='text-center py-8 text-xs text-description'>
غذایی یافت نشد
</div>
) : (
filteredFoods.map((food) => {
const inCart = formik.values.items.some(
(item) => item.foodId === food.id
)
const cartQty = formik.values.items.find(
(item) => item.foodId === food.id
)?.quantity
return (
<div
key={food.id}
className='flex items-center gap-2 p-1.5 rounded-lg hover:bg-[#F8F9FC] transition-colors'
>
{food.images?.[0] ? (
<img
src={food.images[0]}
alt={food.title}
className='w-9 h-9 rounded-lg object-cover flex-shrink-0'
/>
) : (
<div className='w-9 h-9 rounded-lg bg-gray-100 flex-shrink-0' />
)}
<div className='flex-1 min-w-0'>
<div className='text-xs truncate'>{food.title}</div>
<div className='text-[11px] text-description'>
{formatPrice(getFoodUnitPrice(food))}
</div>
</div>
<button
type='button'
onClick={() => onAddFood(food.id)}
className={`flex items-center gap-1 px-2.5 h-7 rounded-lg text-[11px] transition-colors flex-shrink-0 ${
inCart
? 'bg-primary/10 text-primary'
: 'bg-primary text-white'
}`}
>
<Add size={12} color={inCart ? '#000' : '#fff'} />
{inCart ? `×${cartQty}` : 'انتخاب'}
</button>
</div>
)
})
)}
</div>
</div>
{formik.touched.items && formik.errors.items && typeof formik.errors.items === 'string' && (
<div className='text-xs text-red-500 mt-2 flex-shrink-0'>{formik.errors.items}</div>
)}
</div>
)
}
export default CreateOrderItemsSection