You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
4.5 KiB
124 lines
4.5 KiB
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useMarriageAdvisorsQuery } from "@/hooks/marriage/use-marriage-advisors";
|
|
import { localizePath } from "@/translations/config";
|
|
import { useI18n } from "@/translations/provider";
|
|
import NetworkImage from "./network-image";
|
|
|
|
const FALLBACK_AVATAR = "/assets/images/Avatar Image.png";
|
|
|
|
export type AdvisorAvatar = {
|
|
id: string;
|
|
src: string;
|
|
};
|
|
|
|
type AdvisorActionsCardProps = {
|
|
title: string;
|
|
description: string;
|
|
/** Static fallback avatars — used only while the API hasn't responded yet. */
|
|
avatars: AdvisorAvatar[];
|
|
extraCount: number;
|
|
getAdvisorLabel: string;
|
|
getAdvisorHref?: string;
|
|
onGetAdvisor?: () => void;
|
|
className?: string;
|
|
};
|
|
|
|
export function AdvisorActionsCard({
|
|
title,
|
|
description,
|
|
avatars: fallbackAvatars,
|
|
extraCount: fallbackExtraCount,
|
|
getAdvisorLabel,
|
|
getAdvisorHref,
|
|
onGetAdvisor,
|
|
className,
|
|
}: AdvisorActionsCardProps) {
|
|
const { locale } = useI18n();
|
|
const { data, isLoading } = useMarriageAdvisorsQuery();
|
|
const advisors = data?.results ?? [];
|
|
|
|
// Derive real avatars from API response (pick up to 4 with an avatar).
|
|
const realAvatars: AdvisorAvatar[] = advisors
|
|
.filter((a) => a.avatar_url)
|
|
.slice(0, 4)
|
|
.map((a) => ({
|
|
id: a.username,
|
|
src: a.avatar_url ?? FALLBACK_AVATAR,
|
|
}));
|
|
|
|
const displayAvatars =
|
|
realAvatars.length > 0 ? realAvatars : fallbackAvatars;
|
|
|
|
// Show total remaining advisors (capped at advisor count minus shown avatars).
|
|
const displayExtraCount =
|
|
advisors.length > 0
|
|
? Math.max(0, advisors.length - displayAvatars.length)
|
|
: fallbackExtraCount;
|
|
|
|
return (
|
|
<section className={["w-full", className].filter(Boolean).join(" ")}>
|
|
<div className="rounded-[14px] border border-white/80 bg-white/75 px-4 py-3.5 text-left shadow-none backdrop-blur-sm">
|
|
<h2 className="text-[13.5px] leading-tight font-bold text-[#1C1C1C]">
|
|
{title}
|
|
</h2>
|
|
<p className="mt-1.5 max-w-[280px] text-[10.5px] leading-[1.4] font-medium text-[#8A8A8A]">
|
|
{description}
|
|
</p>
|
|
|
|
<div className="mt-3 flex items-center justify-between gap-3">
|
|
<div className="flex items-center shrink-0">
|
|
{isLoading
|
|
? /* ── Shimmer circles while API loads ── */
|
|
Array.from({ length: 3 }).map((_, i) => (
|
|
<span
|
|
key={`shimmer-${i}`}
|
|
className="-ml-1.5 flex h-[28px] w-[28px] overflow-hidden rounded-full border-2 border-white first:ml-0 shimmer-bg"
|
|
/>
|
|
))
|
|
: displayAvatars.map((avatar) => (
|
|
<span
|
|
key={avatar.id}
|
|
className="-ml-1.5 flex h-[28px] w-[28px] overflow-hidden rounded-full border-2 border-white bg-[#E7E7E7] first:ml-0"
|
|
>
|
|
<NetworkImage
|
|
src={avatar.src}
|
|
fallbackSrc={FALLBACK_AVATAR}
|
|
alt=""
|
|
width={28}
|
|
height={28}
|
|
className="h-full w-full object-cover"
|
|
/>
|
|
</span>
|
|
))}
|
|
{!isLoading && displayExtraCount > 0 && (
|
|
<span className="-ml-1.5 flex h-[28px] w-[28px] items-center justify-center rounded-full border-2 border-white bg-[#EDEEF1] text-[10px] font-bold text-[#1C1C1C]">
|
|
+{displayExtraCount}
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
{getAdvisorHref ? (
|
|
<Link
|
|
href={localizePath(getAdvisorHref, locale)}
|
|
className="inline-flex h-[36px] min-w-[105px] px-3.5 shrink-0 items-center justify-center rounded-[9px] border-none bg-[#EBEDF0] text-[12.5px] font-bold text-[#111111] shadow-none hover:bg-[#E2E4E8] active:scale-[0.98] transition-all cursor-pointer whitespace-nowrap"
|
|
>
|
|
{getAdvisorLabel}
|
|
</Link>
|
|
) : (
|
|
<button
|
|
type="button"
|
|
onClick={onGetAdvisor}
|
|
className="inline-flex h-[36px] min-w-[105px] px-3.5 shrink-0 items-center justify-center rounded-[9px] border-none bg-[#EBEDF0] text-[12.5px] font-bold text-[#111111] shadow-none hover:bg-[#E2E4E8] active:scale-[0.98] transition-all cursor-pointer whitespace-nowrap"
|
|
>
|
|
{getAdvisorLabel}
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
export default AdvisorActionsCard;
|