Fix financial page mobile layout, restore shop-discover category chips, unify chip height
- financial/page.tsx: the title+date and amount+status rows used a hard flex-col/flex-row breakpoint switch (sm:), so below 640px every row stacked into 4 separate lines instead of wrapping gracefully — now always flex-row with flex-wrap, min-w-0/shrink-0/truncate so long content wraps instead of the date/badge visually colliding - shops/discover/page.tsx: restored the real category chips (fetched from /shop-categories) alongside All/Pinterest — my earlier pass replaced the whole filter row with just those two, dropping the categories the page never actually had a chance to keep - buttonStyles.ts: btnFilterChip/btnFilterChipActive now have an explicit h-9 (matching toggleBtnClass, used right above them on the shop dashboard) instead of deriving height from padding alone, which made them visibly shorter than the buyer/seller toggle Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -103,33 +103,33 @@ export default function Financial() {
|
||||
key={item._id}
|
||||
className="p-5 border rounded-3xl border-neutral-200 dark:border-neutral-700 bg-white dark:bg-neutral-800 shadow-sm hover:shadow-md transition-all duration-200"
|
||||
>
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-3">
|
||||
<div className="font-medium text-base md:text-lg text-neutral-900 dark:text-white flex items-center gap-2">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2 mb-3">
|
||||
<div className="min-w-0 font-medium text-base md:text-lg text-neutral-900 dark:text-white flex items-center gap-2">
|
||||
{getTransactionType(item.type)}
|
||||
{item.project_title && (
|
||||
<span className="text-sm text-neutral-500 dark:text-neutral-400">
|
||||
<span className="truncate text-sm text-neutral-500 dark:text-neutral-400">
|
||||
({item.project_title})
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-sm text-neutral-500 dark:text-neutral-400 whitespace-nowrap">
|
||||
<div className="shrink-0 text-sm text-neutral-500 dark:text-neutral-400 whitespace-nowrap">
|
||||
{formatDate(item.createdAt)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4">
|
||||
<div className="font-semibold text-lg text-neutral-900 dark:text-white">
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div className="min-w-0 font-semibold text-lg text-neutral-900 dark:text-white">
|
||||
{t("settings.financial.amountPaid")}:{" "}
|
||||
{Number(item.amount).toLocaleString(amountLocale)}{" "}
|
||||
{t("settings.toman")}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex shrink-0 items-center gap-2">
|
||||
<span className="text-neutral-600 dark:text-neutral-300">
|
||||
{t("settings.status")}:
|
||||
</span>
|
||||
<span
|
||||
className={`font-medium px-4 py-1.5 rounded-full text-sm ${getStatusClass(
|
||||
className={`font-medium px-4 py-1.5 rounded-full text-sm whitespace-nowrap ${getStatusClass(
|
||||
item.status
|
||||
)}`}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import Container from "@/components/elements/Container";
|
||||
import LocalePageShell from "@/components/i18n/LocalePageShell";
|
||||
import PageTitle from "@/components/settings/PageTitle";
|
||||
@@ -9,18 +9,46 @@ import TabNavigation from "@/components/TabNavigation";
|
||||
import ShopProductGrid from "@/components/shops/ShopProductGrid";
|
||||
import BoldIcon from "@/components/ui/BoldIcon";
|
||||
import { cn } from "@/lib/utils";
|
||||
import useAxios from "@/hooks/useAxios";
|
||||
import useInfiniteScroll from "@/hooks/useInfiniteScroll";
|
||||
import { IShopProductListing } from "@/types/types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const ALL_ID = "__all__";
|
||||
const PINTEREST_ID = "__pinterest__";
|
||||
|
||||
type ShopCategory = { category: string; sub_categories?: unknown[] };
|
||||
|
||||
export default function ShopDiscoverPage() {
|
||||
const { t } = useTranslation("common");
|
||||
const [pinterestOnly, setPinterestOnly] = useState(false);
|
||||
const { request } = useAxios();
|
||||
const [activeFilter, setActiveFilter] = useState<string>(ALL_ID);
|
||||
const [categories, setCategories] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
request<{ categories?: ShopCategory[] }>("GET", "/shop-categories", null, {
|
||||
noToast: true,
|
||||
})
|
||||
.then((res) =>
|
||||
setCategories(
|
||||
(res?.categories ?? []).map((c) => c.category).filter(Boolean)
|
||||
)
|
||||
)
|
||||
.catch(() => setCategories([]));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const chips = useMemo(() => [ALL_ID, PINTEREST_ID, ...categories], [categories]);
|
||||
|
||||
const { data, isLoading } = useInfiniteScroll({
|
||||
endpoint: "/shop-products/discover",
|
||||
queryKey: ["shop-products-discover", String(pinterestOnly)],
|
||||
params: pinterestOnly ? { pinterest: "true" } : {},
|
||||
queryKey: ["shop-products-discover", activeFilter],
|
||||
params:
|
||||
activeFilter === PINTEREST_ID
|
||||
? { pinterest: "true" }
|
||||
: activeFilter === ALL_ID
|
||||
? {}
|
||||
: { category: activeFilter },
|
||||
});
|
||||
|
||||
const listings: IShopProductListing[] =
|
||||
@@ -33,32 +61,37 @@ export default function ShopDiscoverPage() {
|
||||
<Container className="pb-28">
|
||||
<PageTitle>{t("shops.discoverTitle")}</PageTitle>
|
||||
|
||||
<div className="mb-3 flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setPinterestOnly(false)}
|
||||
className={cn(
|
||||
"rounded-2xl border px-3.5 py-2 text-sm font-medium transition",
|
||||
!pinterestOnly
|
||||
? "border-pink-400 bg-pink-50 text-pink-600 dark:bg-pink-950/30"
|
||||
: "border-neutral-200 text-neutral-700 dark:border-neutral-700 dark:text-neutral-300"
|
||||
)}
|
||||
>
|
||||
{t("shops.allFilter")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setPinterestOnly(true)}
|
||||
className={cn(
|
||||
"flex items-center gap-1.5 rounded-2xl border px-3.5 py-2 text-sm font-medium transition",
|
||||
pinterestOnly
|
||||
? "border-[#E60023] bg-[#E60023]/10 text-[#E60023]"
|
||||
: "border-neutral-200 text-neutral-700 dark:border-neutral-700 dark:text-neutral-300"
|
||||
)}
|
||||
>
|
||||
<BoldIcon name="pinterest" size={14} tinted />
|
||||
{t("shops.pinterestFilter")}
|
||||
</button>
|
||||
<div className="mb-3 flex items-center gap-2 overflow-x-auto pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
|
||||
{chips.map((c) => {
|
||||
const active = activeFilter === c;
|
||||
const isPinterest = c === PINTEREST_ID;
|
||||
const label =
|
||||
c === ALL_ID
|
||||
? t("shops.allFilter")
|
||||
: isPinterest
|
||||
? t("shops.pinterestFilter")
|
||||
: c;
|
||||
return (
|
||||
<button
|
||||
key={c}
|
||||
type="button"
|
||||
onClick={() => setActiveFilter(c)}
|
||||
className={cn(
|
||||
"flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-2xl border px-3.5 py-2 text-sm font-medium transition",
|
||||
active
|
||||
? isPinterest
|
||||
? "border-[#E60023] bg-[#E60023]/10 text-[#E60023]"
|
||||
: "border-pink-400 bg-pink-50 text-pink-600 dark:bg-pink-950/30"
|
||||
: "border-neutral-200 text-neutral-700 dark:border-neutral-700 dark:text-neutral-300"
|
||||
)}
|
||||
>
|
||||
{isPinterest ? (
|
||||
<BoldIcon name="pinterest" size={14} tinted />
|
||||
) : null}
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<ShopProductGrid
|
||||
|
||||
@@ -25,16 +25,19 @@ export const btnPrimary = cn(
|
||||
|
||||
export const btnSecondary = cn(btnDefault, "font-medium text-foreground/90");
|
||||
|
||||
// h-9 اضافه شد تا دقیقاً همارتفاعِ toggleBtnClass باشه (اونجا صریح h-9 پاس داده
|
||||
// میشه) — قبلاً ارتفاعِ این چیپها فقط از py-1.5 میاومد و کوتاهتر از دکمههای
|
||||
// toggle/تایید بود، با اینکه هر دو rounded-3xl (کاملاً pill) بودن
|
||||
export const btnFilterChip = cn(
|
||||
btnBase,
|
||||
"rounded-3xl bg-white/90 px-4 py-1.5 text-xs font-semibold",
|
||||
"flex h-9 items-center justify-center rounded-3xl bg-white/90 px-4 text-xs font-semibold",
|
||||
BTN_BORDER,
|
||||
"dark:bg-neutral-900/90"
|
||||
);
|
||||
|
||||
export const btnFilterChipActive = cn(
|
||||
btnBase,
|
||||
"btn-modern--selected rounded-3xl px-4 py-1.5 text-xs font-semibold text-white",
|
||||
"btn-modern--selected flex h-9 items-center justify-center rounded-3xl px-4 text-xs font-semibold text-white",
|
||||
BTN_BORDER
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user