145 lines
3.8 KiB
TypeScript
145 lines
3.8 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { Icon } from "@iconify/react";
|
|
import { format, differenceInYears, formatDistanceToNow } from "date-fns";
|
|
|
|
export default function Details() {
|
|
const [open, setOpen] = useState(false);
|
|
const [limit, setLimit] = useState(2);
|
|
|
|
const showMore = () => {
|
|
setLimit((prev) => prev + 2);
|
|
};
|
|
|
|
const birthday = new Date("2014-12-8");
|
|
const birthdayStr = format(birthday, "MMMM d, yyyy");
|
|
const age = differenceInYears(new Date(), birthday);
|
|
|
|
const startday = new Date("2025-5-31");
|
|
const startdayStr = format(startday, "MMMM d, yyyy");
|
|
const activitytimes = formatDistanceToNow(startday, { addSuffix: true });
|
|
|
|
type DetailItem = {
|
|
icon: string;
|
|
name: string;
|
|
value?: string;
|
|
};
|
|
|
|
const details: DetailItem[] = [
|
|
{
|
|
icon: "iconoir:calendar",
|
|
name: "Start of activities",
|
|
value: `${startdayStr}(${activitytimes})`,
|
|
},
|
|
{
|
|
icon: "iconoir:birthday-cake",
|
|
name: "Birthday",
|
|
value: `${birthdayStr}(${age}years old)`,
|
|
},
|
|
{
|
|
icon: "guidance:children-must-be-supervised",
|
|
name: "Age",
|
|
value: `${age}years old`,
|
|
},
|
|
{
|
|
icon: "iconoir:map-pin",
|
|
name: "Location",
|
|
value: "Kanagawa, Japan",
|
|
},
|
|
{
|
|
icon: "guidance:unisex-restroom",
|
|
name: "Gender",
|
|
value: "Male",
|
|
},
|
|
{
|
|
icon: "iconoir:globe",
|
|
name: "From",
|
|
value: "Japan",
|
|
},
|
|
{
|
|
icon: "iconoir:translate",
|
|
name: "Language",
|
|
value: "Japanese / English",
|
|
},
|
|
];
|
|
|
|
const visibleDetails = details.slice(0, limit);
|
|
const hasMore = limit < details.length;
|
|
|
|
return (
|
|
<div className="card card-content links">
|
|
<div className="is-flex is-align-items-center" style={{ gap: "0.5em" }}>
|
|
<Icon
|
|
className="title is-4"
|
|
style={{ margin: "0" }}
|
|
icon="iconoir:info-circle"
|
|
/>
|
|
<span className="title is-4" style={{ margin: 0 }}>
|
|
Details
|
|
</span>
|
|
<span
|
|
style={{ marginLeft: "auto", cursor: "pointer" }}
|
|
onClick={() => setOpen((prev) => !prev)}
|
|
>
|
|
<Icon
|
|
className="title is-4"
|
|
icon={open ? "iconoir:nav-arrow-down" : "iconoir:nav-arrow-right"}
|
|
/>
|
|
</span>
|
|
</div>
|
|
|
|
{open && (
|
|
<div className="content links-content" style={{ marginTop: "1em" }}>
|
|
{visibleDetails.map((item, idx) => (
|
|
<div
|
|
key={idx}
|
|
className="card card-content links"
|
|
style={{ marginBottom: "0.5em" }}
|
|
>
|
|
<div
|
|
className="is-flex is-align-items-center"
|
|
style={{ gap: "0.5em" }}
|
|
>
|
|
<Icon
|
|
className="title is-4"
|
|
style={{ margin: "0" }}
|
|
icon={item.icon}
|
|
/>
|
|
<span className="title is-4" style={{ margin: 0 }}>
|
|
{item.name}
|
|
</span>
|
|
{item.value && (
|
|
<span
|
|
style={{
|
|
marginLeft: "auto",
|
|
fontSize: "0.9em",
|
|
color: "#888",
|
|
}}
|
|
>
|
|
{item.value}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
{hasMore && (
|
|
<div
|
|
className="is-flex is-justify-content-center"
|
|
style={{ marginTop: "0.5em" }}
|
|
>
|
|
<button
|
|
onClick={showMore}
|
|
className="button card is-4"
|
|
style={{ width: "auto" }}
|
|
>
|
|
Load More
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|