Vitron-Front/app/routes/profile.wallet._index.tsx
Arda Samadi a67e81ad55 fix(desktop): constrain profile sub-pages so they don't stretch on desktop
These pages are desktop-enabled (they get the DesktopHeader via the /profile
allowlist) but had no desktop layout, so their content stretched edge-to-edge on
wide screens. Add a centered max-width container + a desktop title to the main
profile sub-pages (bookmarks, following, orders, settings, wallet, addresses,
sets). Grids use a wider max-width; single-column lists a narrower one.
ProfilePagesHeader is already lg:hidden, so the mobile header still disappears.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 11:53:28 +03:30

213 lines
7.1 KiB
TypeScript
Raw Permalink 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 { MetaFunction } from "@remix-run/node";
import { Plus } from "lucide-react";
import { useState } from "react";
import ProfilePagesHeader from "../components/ProfilePagesHeader";
import {
useServiceGetWallet,
useServiceCreatePayoutRequest,
} from "../utils/RequestHandler";
import { Button } from "../components/ui/button";
import { Dialog, DialogContent, DialogOverlay } from "../components/ui/dialog";
import AppInput from "../components/AppInput";
import { useToast } from "../hooks/use-toast";
import { getPersianTextOfPrice } from "~/utils/helpers";
import UiProvider from "~/components/UiProvider";
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:
"مدیریت کیف پول و موجودی حساب کاربری شما در ویترون. افزایش موجودی، پیگیری تراکنش‌ها و مدیریت امور مالی.",
},
];
};
export default function Locaton() {
const [isOpen, setIsOpen] = useState(false);
const [amount, setAmount] = useState("");
return (
<div className="flex flex-col gap-6 w-full items-center lg:max-w-[820px] lg:mx-auto lg:pt-6">
<ProfilePagesHeader title="کیف پول" />
<h1 className="hidden lg:block w-full text-[28px] font-extrabold px-4">
کیف پول
</h1>
<MainContent />
<Button
className="fixed bottom-16 z-10 lg:static lg:bottom-auto lg:z-auto lg:mt-4"
size={"xl"}
variant="dark"
onClick={() => setIsOpen(true)}
>
<Plus className="text-WHITE size-6" />
افزایش موجودی
</Button>
<AddFundsDialog
isOpen={isOpen}
onClose={() => setIsOpen(false)}
amount={amount}
setAmount={setAmount}
/>
</div>
);
}
const AddFundsDialog = ({
isOpen,
onClose,
amount,
setAmount,
}: {
isOpen: boolean;
onClose: () => void;
amount: string;
setAmount: (value: string) => void;
}) => {
const { toast } = useToast();
const createPayoutRequest = useServiceCreatePayoutRequest();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
const response = await createPayoutRequest.mutateAsync({
amount,
transaction_type: "deposit",
});
if (response?.paymentUrl) {
window.location.href = response.paymentUrl;
} else {
toast({
title: "خطا در پرداخت",
description: "لینک پرداخت دریافت نشد. لطفا دوباره تلاش کنید.",
variant: "destructive",
});
}
} catch (error) {
toast({
title: "خطا در ثبت درخواست",
description:
"متاسفانه مشکلی در ثبت درخواست پیش آمده است. لطفا دوباره تلاش کنید.",
variant: "destructive",
});
}
};
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogOverlay />
<DialogContent className="p-4 bg-WHITE rounded-[15px] w-[calc(100%-40px)]">
<div className="flex flex-col gap-10">
<div className="flex flex-col gap-3 items-center w-full">
<Plus className="text-primary text-6" />
<p className="text-B12 font-bold mt-1">افزایش موجودی</p>
<AppInput
inputTitle=""
inputValue={amount}
inputPlaceholder="مبلغ را وارد کنید"
inputOnChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setAmount(e.target.value)
}
type="number"
inputDir={amount ? "ltr" : "rtl"}
/>
<p className="text-B12 w-full font-bold">
{getPersianTextOfPrice(amount)}
</p>
</div>
<div className="flex flex-row gap-6 w-full">
<Button
className="w-[100%]"
size={"sm"}
variant="outline"
onClick={() => onClose()}
>
انصراف
</Button>
<Button
disabled={createPayoutRequest.isPending}
className="w-[100%]"
size={"sm"}
variant="dark"
onClick={handleSubmit}
>
{createPayoutRequest.isPending ? (
<>
<div className="relative w-5 h-5 mr-2">
<div className="absolute top-0 left-0 w-full h-full border-2 border-t-primary border-r-transparent border-b-transparent border-l-transparent rounded-full animate-spin"></div>
<div
className="absolute top-0.5 left-0.5 w-4 h-4 border-2 border-t-transparent border-r-primary border-b-transparent border-l-transparent rounded-full animate-spin"
style={{
animationDirection: "reverse",
animationDuration: "0.7s",
}}
></div>
</div>
در حال ثبت...
</>
) : (
"ثبت درخواست"
)}
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
};
const MainContent = () => {
const {
data: walletData,
isFetching: isFetchingWallet,
isError,
refetch,
} = useServiceGetWallet();
const formatBalance = (balance: string) => {
return new Intl.NumberFormat("fa-IR").format(parseInt(balance));
};
return (
<UiProvider
isLoading={isFetchingWallet}
isError={isError}
isEmpty={false}
onRetry={refetch}
type="wallet"
>
<div className="flex flex-col gap-6 items-center mt-[100px]">
<p className="text-R16 text-BLACK2">موجودی شما (تومان): </p>
<p className="text-B24 font-bold">
{walletData ? formatBalance(walletData.balance || "") : "۰"}
</p>
<p className="text-R12 text-GRAY mt-8">
با افزایش موجودی کیف پول، از امکان خرید قسطی استفاده کن!
</p>
</div>
</UiProvider>
);
};