reservation-front/src/pages/CafeOwnerPanel.tsx
2026-07-11 22:38:51 +08:00

104 lines
4.2 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 { ReactNode, useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import Icon from '../components/Icon'
import { useNow } from '../hooks/useNow'
import { CafeSchedule, fetchCafeSchedules } from '../services/campaignApi'
import { getCafeUuid } from '../utils/cafe'
import HostBanner from '../assets/images/banners/Host-banner.jpg'
import { formatPersianNumber } from '../utils/formatNumber'
import { formatMatchLabel } from '../utils/matchCountdown'
function PanelRow({ icon, label, onClick }: { icon: ReactNode; label: string; onClick?: () => void }) {
return (
<button type="button" onClick={onClick} className="flex w-full items-center justify-between py-4">
<div className="flex items-center gap-2">
{icon}
<span className="text-gray-900">{label}</span>
</div>
<Icon name="arrowRight" className="h-5 w-5 text-gray-400" />
</button>
)
}
export default function CafeOwnerPanel() {
const navigate = useNavigate()
const now = useNow()
const [schedules, setSchedules] = useState<CafeSchedule[]>([])
useEffect(() => {
const cafeUuid = getCafeUuid()
if (!cafeUuid) return
fetchCafeSchedules(cafeUuid)
.then(setSchedules)
.catch(() => {})
}, [])
return (
<div className="min-h-screen bg-white pb-20">
<img src={HostBanner} alt="" className="w-full" />
<div className="px-4">
<h1 className="mt-4 text-right text-lg font-bold text-gray-900">پنل کافه</h1>
<div className="mt-2 divide-y divide-gray-100">
<PanelRow
icon={<Icon name="profileCircle" className="h-5 w-5 text-[#4D4D4D]" />}
label="اطلاعات کافه"
onClick={() => navigate('/owner/register', { state: { step: 2 } })}
/>
<PanelRow icon={<Icon name="book" className="h-5 w-5 text-[#4D4D4D]" />} label="افزودن رویداد" onClick={() => navigate('/owner/events/new')} />
</div>
<h2 className="mt-6 text-right font-semibold text-gray-900">رویدادهای فعال شما</h2>
<div className="mt-3 flex flex-col gap-6">
{schedules.map((schedule) => {
const isPast = new Date(schedule.match_event.match_datetime).getTime() <= now.getTime()
const matchLabel = formatMatchLabel(schedule.match_event, now)
return (
<div
key={schedule.uuid}
className={`rounded-2xl px-4 shadow-[0px_4px_12px_0px_#0000001F] ${isPast ? 'opacity-50' : ''}`}
>
<div className="pt-4">
<div className="flex items-center justify-between pb-3">
<p className="text-right text-gray-900">{matchLabel}</p>
{isPast && (
<span className="shrink-0 rounded-full bg-gray-100 px-3 py-1 text-xs text-gray-500">برگزار شده</span>
)}
</div>
<span className="mt-2 inline-block rounded-full bg-[#ECF2F8] px-3 py-1 text-sm text-gray-700">
{formatPersianNumber(schedule.remaining_tickets)} صندلی از {formatPersianNumber(schedule.total_tickets)} باقی مانده
</span>
</div>
<div>
<PanelRow
icon={<Icon name="calendar" className="h-5 w-5 text-[#4D4D4D]" />}
label="مشاهده رزروها"
onClick={() =>
navigate(`/owner/events/${schedule.uuid}/reservations`, {
state: {
event: {
id: schedule.uuid,
matchLabel,
remainingSeats: schedule.remaining_tickets,
totalSeats: schedule.total_tickets,
},
},
})
}
/>
</div>
</div>
)
})}
</div>
</div>
<button type="button" className="fixed bottom-4 right-4 rounded-full bg-[#223D5D] px-5 py-3 text-white shadow-lg">
پشتیبانی
</button>
</div>
)
}