| 1 | "use client"; |
| 2 | |
| 3 | import { |
| 4 | Controller, |
| 5 | type Control, |
| 6 | type UseFormSetValue, |
| 7 | } from "react-hook-form"; |
| 8 | |
| 9 | import { Input } from "@/components/ui/input"; |
| 10 | import { Label } from "@/components/ui/label"; |
| 11 | import { type ThemeColors } from "@/lib/presentation/themes"; |
| 12 | import { cn } from "@/lib/utils"; |
| 13 | import { type ColorKey, type ThemeFormValues } from "../types"; |
| 14 | import { ColorsStep } from "./ColorsStep"; |
| 15 | import { type CreateThemeStep } from "./create-theme-types"; |
| 16 | import { DesignStep } from "./DesignStep"; |
| 17 | import { FontStep } from "./font-step"; |
| 18 | |
| 19 | interface StepContentProps { |
| 20 | step: CreateThemeStep; |
| 21 | control: Control<ThemeFormValues>; |
| 22 | selectedColorTheme: string; |
| 23 | onColorChange: (key: ColorKey, value: string) => void; |
| 24 | onSelectColorTheme: (themeId: string) => void; |
| 25 | setValue: UseFormSetValue<ThemeFormValues>; |
| 26 | isCustomizing?: boolean; |
| 27 | defaultColors?: Partial<ThemeColors>; |
| 28 | } |
| 29 | |
| 30 | export function StepContent({ |
| 31 | step, |
| 32 | control, |
| 33 | selectedColorTheme, |
| 34 | onColorChange, |
| 35 | onSelectColorTheme, |
| 36 | setValue, |
| 37 | isCustomizing, |
| 38 | defaultColors, |
| 39 | }: StepContentProps) { |
| 40 | if (step === "colors") { |
| 41 | return ( |
| 42 | <ColorsStep |
| 43 | control={control} |
| 44 | onColorChange={onColorChange} |
| 45 | onSelectColorTheme={onSelectColorTheme} |
| 46 | selectedColorTheme={selectedColorTheme} |
| 47 | defaultColors={defaultColors} |
| 48 | /> |
| 49 | ); |
| 50 | } |
| 51 | |
| 52 | if (step === "fonts") { |
| 53 | return <FontStep control={control} setValue={setValue} />; |
| 54 | } |
| 55 | |
| 56 | if (step === "design") { |
| 57 | return <DesignStep setValue={setValue} control={control} />; |
| 58 | } |
| 59 | |
| 60 | if (step === "save") { |
| 61 | return ( |
| 62 | <div className="space-y-6 p-8"> |
| 63 | <div className="rounded-lg border-2 border-border bg-card p-8 shadow-lg"> |
| 64 | <h2 className="mb-2 text-2xl font-bold text-foreground"> |
| 65 | Name Your Theme |
| 66 | </h2> |
| 67 | <p className="mb-6 text-sm text-muted-foreground"> |
| 68 | Give your theme a memorable name. |
| 69 | </p> |
| 70 | |
| 71 | <div className="mb-6"> |
| 72 | <Label |
| 73 | htmlFor="theme-name" |
| 74 | className="mb-2 block text-sm font-semibold text-foreground" |
| 75 | > |
| 76 | Theme Name |
| 77 | </Label> |
| 78 | <Controller |
| 79 | name="name" |
| 80 | control={control} |
| 81 | render={({ field }) => ( |
| 82 | <Input |
| 83 | id="theme-name" |
| 84 | {...field} |
| 85 | placeholder="Enter a name for your theme" |
| 86 | className="w-full rounded-lg border-2 border-border bg-background px-4 py-3 text-foreground transition-all outline-none focus:border-blue-600 focus:ring-2 focus:ring-blue-600/20" |
| 87 | /> |
| 88 | )} |
| 89 | /> |
| 90 | </div> |
| 91 | |
| 92 | {!isCustomizing && ( |
| 93 | <div className="mb-6"> |
| 94 | <Label className="mb-3 block text-sm font-semibold text-foreground"> |
| 95 | Theme Mode |
| 96 | </Label> |
| 97 | <Controller |
| 98 | name="mode" |
| 99 | control={control} |
| 100 | render={({ field }) => ( |
| 101 | <div className="grid grid-cols-2 gap-4"> |
| 102 | <button |
| 103 | type="button" |
| 104 | onClick={() => field.onChange("light")} |
| 105 | className={cn( |
| 106 | "rounded-lg border-2 p-6 text-left transition-all duration-200", |
| 107 | field.value === "light" |
| 108 | ? "border-blue-600 bg-blue-50 dark:bg-blue-950/30" |
| 109 | : "border-border hover:border-muted-foreground", |
| 110 | )} |
| 111 | > |
| 112 | <div className="flex items-start gap-3"> |
| 113 | <div |
| 114 | className={cn( |
| 115 | "mt-0.5 flex h-5 w-5 items-center justify-center rounded-full border-2 transition-all", |
| 116 | field.value === "light" |
| 117 | ? "border-blue-600 bg-blue-600" |
| 118 | : "border-border", |
| 119 | )} |
| 120 | > |
| 121 | {field.value === "light" && ( |
| 122 | <div className="h-2.5 w-2.5 rounded-full bg-white" /> |
| 123 | )} |
| 124 | </div> |
| 125 | <div className="flex-1"> |
| 126 | <h3 className="mb-1 font-semibold text-foreground"> |
| 127 | Light Mode |
| 128 | </h3> |
| 129 | <p className="text-sm text-muted-foreground"> |
| 130 | Optimized for light backgrounds |
| 131 | </p> |
| 132 | </div> |
| 133 | </div> |
| 134 | </button> |
| 135 | |
| 136 | <button |
| 137 | type="button" |
| 138 | onClick={() => field.onChange("dark")} |
| 139 | className={cn( |
| 140 | "rounded-lg border-2 p-6 text-left transition-all duration-200", |
| 141 | field.value === "dark" |
| 142 | ? "border-blue-600 bg-blue-50 dark:bg-blue-950/30" |
| 143 | : "border-border hover:border-muted-foreground", |
| 144 | )} |
| 145 | > |
| 146 | <div className="flex items-start gap-3"> |
| 147 | <div |
| 148 | className={cn( |
| 149 | "mt-0.5 flex h-5 w-5 items-center justify-center rounded-full border-2 transition-all", |
| 150 | field.value === "dark" |
| 151 | ? "border-blue-600 bg-blue-600" |
| 152 | : "border-border", |
| 153 | )} |
| 154 | > |
| 155 | {field.value === "dark" && ( |
| 156 | <div className="h-2.5 w-2.5 rounded-full bg-white" /> |
| 157 | )} |
| 158 | </div> |
| 159 | <div className="flex-1"> |
| 160 | <h3 className="mb-1 font-semibold text-foreground"> |
| 161 | Dark Mode |
| 162 | </h3> |
| 163 | <p className="text-sm text-muted-foreground"> |
| 164 | Optimized for dark backgrounds |
| 165 | </p> |
| 166 | </div> |
| 167 | </div> |
| 168 | </button> |
| 169 | </div> |
| 170 | )} |
| 171 | /> |
| 172 | </div> |
| 173 | )} |
| 174 | </div> |
| 175 | </div> |
| 176 | ); |
| 177 | } |
| 178 | |
| 179 | return null; |
| 180 | } |
| 181 |