1import { enumOf, Int } from "@akanjs/base";
2import { isPhoneNumber } from "@akanjs/common";
3import { via } from "@akanjs/constant";
4
5export class ServeType extends enumOf("serveType", ["forHere", "takeOut", "delivery"] as const) {}
6
7// ...existing code...
8
9export class IcecreamOrderInput extends via((field) => ({
10 serveType: field(ServeType, { default: "forHere" }),
11 size: field(Int, { default: 50 }),
12 toppings: field([Topping]),
13 phone: field(String, { validate: isPhoneNumber })
14})) {}
15
16// ...existing code...1// ...existing code...
2
3export const dictionary = modelDictionary(["en", "ko"])
4// ...existing code...
5 .model<IcecreamOrder>((t) => ({
6 serveType: t(["Serve Type", "서빙 타입"]).desc(["Serve type of the icecream order", "아이스크림 주문의 서빙 타입"]),
7 size: t(["Size", "사이즈"]).desc(["Size of the icecream order", "아이스크림 주문의 사이즈"]),
8 toppings: t(["Toppings", "토핑"]).desc(["Toppings of the icecream order", "아이스크림 주문의 토핑"]),
9 phone: t(["Phone", "전화번호"]).desc(["Phone number of the icecream order", "아이스크림 주문의 전화번호"]),
10 status: t(["Status", "상태"]).desc(["Status of the icecream order", "아이스크림 주문의 상태"]),
11 }))
12 .enum<ServeType>("serveType", (t) => ({
13 forHere: t(["For Here", "매장 식사"]).desc(["For Here serve type", "매장 식사 서빙 타입"]),
14 takeOut: t(["Take Out", "포장 주문"]).desc(["Take Out serve type", "포장 주문 서빙 타입"]),
15 delivery: t(["Delivery", "배달"]).desc(["Delivery serve type", "배달 서빙 타입"]),
16 }))
17// ...existing code...1"use client";
2import { Field, Layout } from "@akanjs/ui";
3import { cnst, st, usePage } from "@koyo/client";
4
5interface IcecreamOrderEditProps {
6 className?: string;
7}
8
9export const General = ({ className }: IcecreamOrderEditProps) => {
10 const icecreamOrderForm = st.use.icecreamOrderForm();
11 const { l } = usePage();
12 return (
13 <Layout.Template className={className}>
14 <Field.ToggleSelect
15 label={l("icecreamOrder.size")}
16 items={[50, 100, 200].map((size) => ({ label: `${size}cc`, value: size }))}
17 value={icecreamOrderForm.size}
18 onChange={st.do.setSizeOnIcecreamOrder}
19 />
20 <Field.MultiToggleSelect
21 label={l("icecreamOrder.toppings")}
22 items={cnst.Topping}
23 value={icecreamOrderForm.toppings}
24 onChange={st.do.setToppingsOnIcecreamOrder}
25 />
26 <Field.Phone
27 label={l("icecreamOrder.phone")}
28 placeholder="010-0000-0000"
29 value={icecreamOrderForm.phone}
30 onChange={st.do.setPhoneOnIcecreamOrder}
31 />
32 </Layout.Template>
33 );
34};
35 1import { Link, Load } from "@akanjs/ui";
2import { usePage } from "@koyo/client";
3import { SetLang } from "@koyo/ui";
4
5export default function Page() {
6 const { l } = usePage();
7 return (
8 <Load.Page
9 of={Page}
10 loader={async () => {
11 return await Promise.resolve({} as const);
12 }}
13 render={() => {
14 return (
15 <div className="flex min-h-screen flex-col items-center justify-center bg-linear-to-br from-purple-50 via-pink-50 to-blue-50 p-6">
16 <div className="absolute top-6 right-6 flex gap-2">
17 <Link.Lang
18 lang="en"
19 className="rounded-lg bg-white/70 px-4 py-2 font-semibold text-gray-700 backdrop-blur-sm transition-all duration-200 hover:bg-white hover:shadow-md"
20 >
21 English
22 </Link.Lang>
23 <Link.Lang
24 lang="ko"
25 className="rounded-lg bg-white/70 px-4 py-2 font-semibold text-gray-700 backdrop-blur-sm transition-all duration-200 hover:bg-white hover:shadow-md"
26 >
27 한국어
28 </Link.Lang>
29 </div>
30 <div className="w-full max-w-4xl space-y-8 text-center">
31 <div className="space-y-4">
32 <h1 className="bg-linear-to-r from-purple-600 via-pink-500 to-blue-500 bg-clip-text text-7xl font-bold text-transparent duration-1000 md:text-8xl">
33 Koyo
34 </h1>
35 <p className="text-2xl font-light text-gray-700 delay-150 duration-1000 md:text-3xl">
36 {l.trans({ en: "Korean Yogurt Ice Cream", ko: "한국 요거트 아이스크림" })}
37 </p>
38 <div className="flex items-center justify-center gap-2 text-lg text-gray-600 delay-300 duration-1000">
39 <span className="text-3xl">🍦</span>
40 <span>{l.trans({ en: "Fresh • Creamy • Delicious", ko: "신선한 • 부드러운 • 맛있는" })}</span>
41 <span className="text-3xl">🍦</span>
42 </div>
43 </div>
44 <div className="flex flex-col items-center gap-4 pt-8 delay-500 duration-1000 sm:flex-row sm:justify-center">
45 <Link
46 href="/customer/icecreamOrder/new?serveType=forHere"
47 className="inline-flex w-full items-center justify-center gap-3 rounded-full bg-linear-to-r from-purple-600 via-pink-500 to-blue-500 px-10 py-6 text-2xl font-semibold text-white shadow-2xl transition-all duration-300 hover:scale-105 hover:from-purple-700 hover:via-pink-600 hover:to-blue-600 hover:shadow-purple-500/50 active:scale-95 sm:w-auto"
48 >
49 <span className="text-4xl">🍽️</span>
50 {l.trans({ en: "For Here", ko: "매장 식사" })}
51 </Link>
52 <Link
53 href="/customer/icecreamOrder/new?serveType=takeout"
54 className="inline-flex w-full items-center justify-center gap-3 rounded-full bg-linear-to-r from-blue-600 via-indigo-500 to-purple-500 px-10 py-6 text-2xl font-semibold text-white shadow-2xl transition-all duration-300 hover:scale-105 hover:from-blue-700 hover:via-indigo-600 hover:to-purple-600 hover:shadow-blue-500/50 active:scale-95 sm:w-auto"
55 >
56 <span className="text-4xl">🛍️</span>
57 {l.trans({ en: "Take Out", ko: "포장 주문" })}
58 </Link>
59 </div>
60 </div>
61 </div>
62 );
63 }}
64 />
65 );
66}
67 1import { Link, Load } from "@akanjs/ui";
2import { usePage } from "@koyo/client";
3
4export default function Page() {
5 const { l } = usePage();
6 return (
7 <Load.Page
8 of={Page}
9 loader={async () => {
10 return await Promise.resolve({} as const);
11 }}
12 render={() => {
13 return (
14 <div className="flex min-h-screen flex-col items-center justify-center bg-linear-to-br from-purple-50 via-pink-50 to-blue-50 p-6">
15 <div className="w-full max-w-2xl space-y-8 text-center">
16 <div className="flex justify-center">
17 <div className="flex h-32 w-32 items-center justify-center rounded-full bg-linear-to-r from-green-400 to-emerald-500 text-7xl shadow-2xl">
18 ✓
19 </div>
20 </div>
21 <div className="space-y-4">
22 <h1 className="bg-linear-to-r from-purple-600 via-pink-500 to-blue-500 bg-clip-text text-5xl font-bold text-transparent md:text-6xl">
23 {l.trans({ en: "Order Placed!", ko: "주문 완료!" })}
24 </h1>
25 </div>
26 <div className="rounded-2xl bg-white/70 p-8 shadow-xl backdrop-blur-sm">
27 <div className="space-y-3">
28 <div className="flex items-center justify-center gap-2 text-lg text-gray-700">
29 <span className="text-3xl">🎉</span>
30 <span className="font-semibold">
31 {l.trans({ en: "We're preparing your order", ko: "주문을 준비하고 있습니다" })}
32 </span>
33 </div>
34 <p className="text-gray-600">
35 {l.trans({
36 en: "Please wait for your order number to be called",
37 ko: "주문 번호가 호출될 때까지 기다려 주세요",
38 })}
39 </p>
40 </div>
41 </div>
42 <div className="pt-4">
43 <Link
44 href="/customer/icecreamOrder"
45 className="inline-flex items-center justify-center gap-3 rounded-full bg-linear-to-r from-purple-600 via-pink-500 to-blue-500 px-12 py-6 text-2xl font-semibold text-white shadow-2xl transition-all hover:scale-105 hover:from-purple-700 hover:via-pink-600 hover:to-blue-600 hover:shadow-purple-500/50 active:scale-95"
46 >
47 <span className="text-4xl">🏠</span>
48 {l.trans({ en: "Place New Order", ko: "새 주문하기" })}
49 </Link>
50 </div>
51 </div>
52 </div>
53 );
54 }}
55 />
56 );
57}1import { Load } from "@akanjs/ui";
2import { cnst, IcecreamOrder, usePage } from "@koyo/client";
3
4interface PageProps {
5 searchParams: Promise<{
6 serveType?: cnst.ServeType["value"];
7 }>;
8}
9export default function Page({ searchParams }: PageProps) {
10 const { l } = usePage();
11 return (
12 <Load.Page
13 of={Page}
14 loader={async () => {
15 const { serveType } = await searchParams;
16 const icecreamOrderForm: Partial<cnst.IcecreamOrder> = { serveType };
17 return await Promise.resolve({ icecreamOrderForm });
18 }}
19 render={({ icecreamOrderForm }) => (
20 <div className="flex min-h-screen flex-col items-center justify-center bg-linear-to-br from-purple-50 via-pink-50 to-blue-50 p-6">
21 <div className="w-full max-w-2xl space-y-8">
22 <div className="space-y-4 text-center">
23 <div className="flex justify-center">
24 <span className="text-8xl">🍦</span>
25 </div>
26 <h1 className="bg-linear-to-r from-purple-600 via-pink-500 to-blue-500 bg-clip-text text-5xl font-bold text-transparent md:text-6xl">
27 {l("base.createModel", { model: l("icecreamOrder.modelName") })}
28 </h1>
29 <p className="text-xl font-light text-gray-600">
30 {l.trans({ en: "Customize your perfect treat", ko: "나만의 완벽한 디저트를 만들어보세요" })}
31 </p>
32 </div>
33 <Load.Edit
34 className="flex flex-col items-center"
35 sliceName="icecreamOrderInPublic"
36 edit={icecreamOrderForm}
37 type="form"
38 onCancel="back"
39 onSubmit="/customer/icecreamOrder/success"
40 >
41 <IcecreamOrder.Template.General />
42 </Load.Edit>
43 </div>
44 </div>
45 )}
46 />
47 );
48}1"use client";
2import { clsx } from "@akanjs/client";
3import { Field, Layout } from "@akanjs/ui";
4import { cnst, st, usePage } from "@koyo/client";
5
6interface IcecreamOrderEditProps {
7 className?: string;
8}
9
10export const General = ({ className }: IcecreamOrderEditProps) => {
11 const icecreamOrderForm = st.use.icecreamOrderForm();
12 const { l } = usePage();
13 return (
14 <Layout.Template className={clsx("w-full space-y-6", className)}>
15 <div className="rounded-2xl bg-white/70 p-8 shadow-xl backdrop-blur-sm">
16 <div className="space-y-6">
17 <div className="flex items-center gap-3">
18 <span className="text-3xl">📏</span>
19 <h2 className="text-2xl font-semibold text-gray-800">{l("icecreamOrder.size")}</h2>
20 </div>
21 <Field.ToggleSelect
22 items={[50, 100, 200].map((size) => ({ label: `${size}cc`, value: size }))}
23 value={icecreamOrderForm.size}
24 onChange={st.do.setSizeOnIcecreamOrder}
25 />
26 </div>
27 </div>
28 <div className="rounded-2xl bg-white/70 p-8 shadow-xl backdrop-blur-sm">
29 <div className="space-y-6">
30 <div className="flex items-center gap-3">
31 <span className="text-3xl">🍓</span>
32 <h2 className="text-2xl font-semibold text-gray-800">{l("icecreamOrder.toppings")}</h2>
33 </div>
34 <Field.MultiToggleSelect
35 items={cnst.Topping}
36 value={icecreamOrderForm.toppings}
37 onChange={st.do.setToppingsOnIcecreamOrder}
38 />
39 </div>
40 </div>
41 <div className="rounded-2xl bg-white/70 p-8 shadow-xl backdrop-blur-sm">
42 <div className="space-y-6">
43 <div className="flex items-center gap-3">
44 <span className="text-3xl">📱</span>
45 <h2 className="text-2xl font-semibold text-gray-800">{l("icecreamOrder.phone")}</h2>
46 </div>
47 <Field.Phone
48 placeholder="010-0000-0000"
49 value={icecreamOrderForm.phone}
50 onChange={st.do.setPhoneOnIcecreamOrder}
51 />
52 </div>
53 </div>
54 </Layout.Template>
55 );
56};