1
2// File: apps/koyo/lib/icecreamOrder/IcecreamOrder.Zone.tsx
3"use client";
4import { Model } from "@akanjs/ui";
5import { DefaultOf } from "@akanjs/constant";
6
7interface CardProps {
8 className?: string;
9 init: ClientInit<"icecreamOrder", cnst.LightIcecreamOrder>;
10}
11export const Card = ({ className, init }: CardProps) => {
12 return (
13 <>
14 <Load.Units
15 className={className}
16 init={init}
17 renderItem={(icecreamOrder: cnst.LightIcecreamOrder) => (
18 <IcecreamOrder.Unit.Card
19 key={icecreamOrder.id}
20 href={`/icecreamOrder/${icecreamOrder.id}`}
21 icecreamOrder={icecreamOrder}
22 />
23 )}
24 />
25 <Model.ViewEditModal
26 sliceName="icecreamOrderInPublic"
27 renderTitle={(icecreamOrder: DefaultOf<cnst.IcecreamOrder>) =>
28 `IcecreamOrder - ${icecreamOrder.id ? icecreamOrder.id : "New"}`
29 }
30 renderView={(icecreamOrder: cnst.IcecreamOrder) => (
31 <IcecreamOrder.View.General className="w-full" icecreamOrder={icecreamOrder} />
32 )}
33 renderTemplate={() => <IcecreamOrder.Template.General />}
34 />
35 </>
36 );
37};
38
39// ... existing code ...
401
2// File: apps/koyo/lib/icecreamOrder/IcecreamOrder.Unit.tsx
3import { clsx, ModelProps } from "@akanjs/client";
4import { Model } from "@akanjs/ui";
5import { cnst, usePage } from "@koyo/client";
6
7export const Card = ({ icecreamOrder }: ModelProps<"icecreamOrder", cnst.LightIcecreamOrder>) => {
8 const { l } = usePage();
9 return (
10 <div className="group flex h-36 w-full overflow-hidden rounded-xl bg-linear-to-br from-pink-100 via-yellow-50 to-pink-200 px-8 py-6 shadow-md transition-all duration-300 hover:shadow-xl">
11 <div className="flex w-full flex-col justify-center">
12 <div className="flex items-center gap-2 text-lg font-semibold text-pink-700">
13 <span className="inline-block rounded bg-pink-200 px-2 py-1 text-xs font-bold tracking-wider uppercase">
14 {l("icecreamOrder.id")}
15 </span>
16 <span className="ml-2 font-mono text-pink-900">{icecreamOrder.id}</span>
17 </div>
18 <div className="mt-4 flex items-center gap-2">
19 <span className="inline-block rounded bg-yellow-200 px-2 py-1 text-xs font-bold tracking-wider text-yellow-800 uppercase">
20 {l("icecreamOrder.status")}
21 </span>
22 <span
23 className={clsx("ml-2 rounded-full px-3 py-1 text-sm font-semibold", {
24 "bg-green-100 text-green-700": icecreamOrder.status === "active",
25 "bg-blue-100 text-blue-700": icecreamOrder.status === "processing",
26 "bg-red-100 text-red-700": icecreamOrder.status === "served",
27 "bg-purple-100 text-purple-700": icecreamOrder.status === "finished",
28 "bg-gray-100 text-gray-700": icecreamOrder.status === "canceled",
29 })}
30 >
31 {l(`icecreamOrderStatus.${icecreamOrder.status}`)}
32 </span>
33 </div>
34 </div>
35 <div className="bg-base-100/50 flex items-center justify-center gap-2 rounded-xl p-4">
36 <Model.ViewWrapper sliceName="icecreamOrder" modelId={icecreamOrder.id}>
37 <button className="btn btn-primary">
38 <span>{l.trans({ en: "View", ko: "보기" })}</span>
39 </button>
40 </Model.ViewWrapper>
41 </div>
42 </div>
43 );
44};1// File: apps/koyo/lib/icecreamOrder/IcecreamOrder.View.tsx
2import { clsx } from "@akanjs/client";
3import { cnst, usePage } from "@koyo/client";
4
5interface IcecreamOrderViewProps {
6 className?: string;
7 icecreamOrder: cnst.IcecreamOrder;
8}
9
10export const General = ({ className, icecreamOrder }: IcecreamOrderViewProps) => {
11 const { l } = usePage();
12 return (
13 <div className={clsx(className, "mx-auto w-full space-y-6 rounded-xl p-8 shadow-lg")}>
14 {/* Header with icon and title */}
15 <div className="flex items-center gap-3 border-b pb-4">
16 <span className="text-3xl font-extrabold text-pink-600">🍦</span>
17 <span className="text-2xl font-bold">{l("icecreamOrder.modelName")}</span>
18 <span className="ml-auto text-xs text-base-content/50">#{icecreamOrder.id}</span>
19 </div>
20
21 {/* Order details in a grid layout */}
22 <div className="grid grid-cols-2 gap-x-6 gap-y-4">
23 {/* Size information */}
24 <div className="font-semibold text-base-content/50">{l("icecreamOrder.size")}</div>
25 <div>{icecreamOrder.size} cc</div>
26
27 {/* Toppings information */}
28 <div className="font-semibold text-base-content/50">{l("icecreamOrder.toppings")}</div>
29 <div className="flex flex-wrap gap-2">
30 {icecreamOrder.toppings.length === 0 ? (
31 <span className="italic text-gray-400">
32 {l.trans({ en: "No toppings", ko: "토핑 없음" })}
33 </span>
34 ) : (
35 icecreamOrder.toppings.map((topping) => (
36 <span
37 key={topping}
38 className="inline-block rounded-full bg-pink-100 px-2 py-1 text-xs font-medium text-pink-700"
39 >
40 {l(`topping.${topping}`)}
41 </span>
42 ))
43 )}
44 </div>
45
46 {/* Status information */}
47 <div className="font-semibold text-base-content/50">{l("icecreamOrder.status")}</div>
48 <div>
49 <span
50 className={clsx("inline-block rounded-full px-2 py-1 text-xs font-semibold", {
51 "bg-green-100 text-green-700": icecreamOrder.status === "active",
52 "bg-yellow-100 text-yellow-700": icecreamOrder.status === "processing",
53 "bg-red-100 text-red-700": icecreamOrder.status === "served",
54 "bg-purple-100 text-purple-700": icecreamOrder.status === "finished",
55 "bg-gray-100 text-gray-700": icecreamOrder.status === "canceled",
56 })}
57 >
58 {l(`icecreamOrderStatus.${icecreamOrder.status}`)}
59 </span>
60 </div>
61
62 {/* Timestamps */}
63 <div className="font-semibold text-base-content/50">{l("icecreamOrder.createdAt")}</div>
64 <div className="text-gray-500">{icecreamOrder.createdAt.format("YYYY-MM-DD HH:mm:ss")}</div>
65
66 <div className="font-semibold text-base-content/50">{l("icecreamOrder.updatedAt")}</div>
67 <div className="text-gray-500">{icecreamOrder.updatedAt.format("YYYY-MM-DD HH:mm:ss")}</div>
68 </div>
69 </div>
70 );
71};