158 lines
5.3 KiB
TypeScript
158 lines
5.3 KiB
TypeScript
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>
|
||
);
|
||
}
|