reservation-front/src/pages/CafeOwnerPanel.tsx
2026-07-22 11:57:05 +03:30

158 lines
5.3 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 SupportButton from "../components/SupportButton";
import LogoutModal from "../components/LogoutModal";
import { logout } from "../utils/logout";
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[]>([]);
const [showLogout, setShowLogout] = useState(false);
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="relative">
<button
type="button"
onClick={() => setShowLogout(true)}
className="absolute left-3 top-3 flex items-center gap-1.5 rounded-full bg-white/90 px-3 py-1.5 text-sm font-semibold text-gray-800 shadow"
>
<Icon name="logout" className="h-4 w-4 font-medium" />
خروج
</button>
</div>
{showLogout && (
<LogoutModal
onConfirm={() => {
logout();
navigate("/cafe/login");
}}
onCancel={() => setShowLogout(false)}
/>
)}
<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>
<SupportButton className="fixed bottom-4 right-4 rounded-full bg-[#223D5D] px-5 py-3 font-semibold text-white shadow-lg" />
</div>
);
}