Vitron-Front/app/routes/store.$storeId.financial-dashboard.reports.tsx
Arda Samadi 16389fdd85 fix(desktop): lay out dashboard sub-pages + form pages for wide screens
- HeaderWithSupport is now lg:hidden (all its callers are desktop-full-width
  store/profile pages), removing the stray mobile back+support bar on desktop.
- Constrain + title the previously mobile-only pages so their content doesn't
  stretch edge-to-edge on desktop: store edit/create form (StoreForm), add
  product, shipping method, financial sub-pages (cash-funds/reports/
  transactions), order detail, instagram auth; and profile add/edit address,
  set detail, and payment result. Forms use a narrow centered column, lists/
  details a wider one. Transactions keeps its filter button (header restyled,
  not hidden).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 12:06:13 +03:30

172 lines
6.4 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { Sun, Waves, Loader2 } from "lucide-react";
import HeaderWithSupport from "../components/HeaderWithSupport";
import PersianDatePicker from "../components/PersianDatePicker";
import { useEffect, useState } from "react";
import { useSearchParams, useNavigate, useParams } from "react-router-dom";
import { formatPrice, safeGoBack } from "../utils/helpers";
import { useServiceGetReport } from "../requestHandler/use-wallet-hooks";
import { useRequireOwner } from "../hooks/useStoreOwnership";
import jMoment from "moment-jalaali";
import { MetaFunction } from "@remix-run/node";
export default function Reports() {
const navigate = useNavigate();
const { storeId } = useParams();
useRequireOwner(storeId); // financial is owner-only
const handleBack = () => {
safeGoBack(navigate);
};
const [fromDate, setFromDate] = useState<string>("");
const [toDate, setToDate] = useState<string>("");
const [searchParams, setSearchParams] = useSearchParams();
// Convert Persian date to Gregorian ISO string
const convertPersianToGregorian = (persianDate: string): string => {
// Persian date format is expected to be YYYY/MM/DD
const [year, month, day] = persianDate.split("/");
const jMomentDate = jMoment(`${year}/${month}/${day}`, "jYYYY/jM/jD");
return jMomentDate.format("YYYY-MM-DD");
};
// Get filters for API
const getFilters = () => {
const filters: { fromDate?: string; toDate?: string } = {};
if (fromDate) {
try {
filters.fromDate = convertPersianToGregorian(fromDate);
} catch (error) {
console.error("Error converting fromDate:", error);
}
}
if (toDate) {
try {
filters.toDate = convertPersianToGregorian(toDate);
} catch (error) {
console.error("Error converting toDate:", error);
}
}
return Object.keys(filters).length > 0 ? filters : undefined;
};
// Fetch report data
const { data: reportData, isLoading } = useServiceGetReport(getFilters());
useEffect(() => {
const params: Record<string, string> = {};
if (fromDate) params.fromDate = fromDate;
if (toDate) params.toDate = toDate;
setSearchParams(params, { replace: true });
}, [fromDate, toDate, setSearchParams]);
return (
<div className="bg-WHITE lg:max-w-[900px] lg:mx-auto lg:w-full lg:pt-6">
<HeaderWithSupport title="گزارش مالی" onBack={handleBack} />
<h1 className="hidden lg:block text-[28px] font-extrabold px-4 mb-2">
گزارش مالی
</h1>
<div className="bg-WHITE p-4 w-full flex gap-2 items-center">
<div className="w-full">
<PersianDatePicker
value={fromDate}
onChange={setFromDate}
placeholder="از تاریخ"
label=""
/>
</div>
{/* To Date */}
<div className="w-full">
<PersianDatePicker
value={toDate}
onChange={setToDate}
placeholder="تا تاریخ"
label=""
/>
</div>
</div>
<div className="w-full px-4">
{isLoading ? (
<div className="flex items-center justify-center py-8">
<Loader2 className="w-8 h-8 animate-spin" />
</div>
) : reportData ? (
<>
<div className="w-full py-4 flex flex-col border-b gap-6">
<div className="w-full flex flex-col gap-2">
<div className="flex gap-2">
<Waves size={20} className="text-blue-500" />
<p className="text-B14 font-bold">میزان فروش کل (تومان):</p>
</div>
<p className="text-R12 text-GRAY">
جمع مبلغ پرداختشده توسط خریداران
</p>
<p className="text-B18 font-bold text-BLACK">
{formatPrice(reportData.totalSales.toString())}
</p>
</div>
</div>
<div className="w-full py-4 flex border-b flex-col gap-6">
<div className="w-full flex flex-col gap-2">
<div className="flex gap-2">
<Sun size={20} className="text-blue-500" />
<p className="text-B14 font-bold">
وضعیت تسویه حساب (تومان):
</p>
</div>
<p className="text-R12 text-GRAY">
وضعیت واریز درآمد در این بازه
</p>
<p className="text-B14 font-bold">
تسویه شده: {formatPrice(reportData.totalSettled.toString())}
</p>
<p className="text-B14 text-GRAY font-bold">
در انتظار پرداخت:{" "}
{formatPrice(reportData.pendingSettlement.toString())}
</p>
</div>
</div>
</>
) : (
<div className="flex flex-col items-center justify-center py-8 text-GRAY">
<p className="text-B16">خطا در بارگذاری گزارش</p>
<p className="text-R12 mt-2">لطفا مجددا تلاش کنید</p>
</div>
)}
</div>
</div>
);
}
export const meta: MetaFunction = () => {
return [
{ title: "گزارش مالی - ویترون" },
{
name: "description",
content:
"مدیریت و مشاهده تمام گزارش مالی در فروشگاه شما. فیلتر بر اساس وضعیت و جستجو در گزارش مالی.",
},
{
name: "keywords",
content: "گزارش مالی، مدیریت گزارش مالی، فروشگاه، مشتری، ویترون",
},
{ name: "robots", content: "noindex, follow" },
{ property: "og:title", content: "گزارش مالی - ویترون" },
{
property: "og:description",
content:
"مدیریت و مشاهده تمام گزارش مالی در فروشگاه شما. فیلتر بر اساس وضعیت و جستجو در گزارش مالی.",
},
{ property: "og:type", content: "website" },
{ name: "twitter:card", content: "summary" },
{ name: "twitter:title", content: "گزارش مالی - ویترون" },
{
name: "twitter:description",
content:
"مدیریت و مشاهده تمام گزارش مالی در فروشگاه شما. فیلتر بر اساس وضعیت و جستجو در گزارش مالی.",
},
];
};