Skip to content

Commit 28ea9c7

Browse files
committed
feat(arf): add resizable image inputs
1 parent 1569802 commit 28ea9c7

4 files changed

Lines changed: 49 additions & 9 deletions

File tree

src/components/inputs/image-upload.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Button } from "@/components/ui/button";
1212
import { FormControl, FormLabel } from "@/components/ui/form";
1313
import { Input } from "@/components/ui/input";
1414
import { ImageType } from "@/config/enums";
15+
import type { ImageSize } from "@/features/abstract-resource-form";
1516
import { ApiImage, uploadFile, useMutationWrapper } from "@/features/backend";
1617
import { declineNoun } from "@/features/polish";
1718
import type { Resource } from "@/features/resources";
@@ -20,15 +21,40 @@ import type {
2021
ResourceSchemaKey,
2122
} from "@/features/resources/types";
2223
import { getToastMessages } from "@/lib/get-toast-messages";
24+
import { cn } from "@/lib/utils";
2325
import type { WrapperProps } from "@/types/components";
2426

2527
import { ImagePreviewModal } from "../presentation/image-preview-modal";
2628

27-
function InputBox({ children }: WrapperProps) {
29+
function getImageSizeClasses(size: ImageSize): string {
30+
switch (size) {
31+
case "small": {
32+
return "md:size-32";
33+
}
34+
case "medium": {
35+
return "md:size-48";
36+
}
37+
case "large": {
38+
return "md:size-64";
39+
}
40+
case "wide": {
41+
return "md:h-48 md:w-full aspect-video";
42+
}
43+
}
44+
}
45+
46+
function InputBox({
47+
children,
48+
size = "medium",
49+
}: WrapperProps & { size?: ImageSize }) {
2850
return (
2951
<InputSlot
3052
renderAs="div"
31-
className="aspect-video h-fit max-h-48 w-full overflow-hidden rounded-lg md:size-48"
53+
className={cn(
54+
"h-fit w-full overflow-hidden rounded-lg",
55+
size !== "wide" && "aspect-video max-h-48",
56+
getImageSizeClasses(size),
57+
)}
3258
>
3359
{children}
3460
</InputSlot>
@@ -41,6 +67,7 @@ export function ImageUpload<T extends Resource>({
4167
value,
4268
label,
4369
type = ImageType.Logo,
70+
size = "medium",
4471
existingImage,
4572
resourceData,
4673
disabled,
@@ -50,6 +77,7 @@ export function ImageUpload<T extends Resource>({
5077
onChange: (value: string | null) => void;
5178
label: string;
5279
type?: ImageType;
80+
size?: ImageSize;
5381
existingImage?: ReactNode;
5482
resourceData?: ResourceFormValues<T>;
5583
disabled?: boolean;
@@ -112,7 +140,7 @@ export function ImageUpload<T extends Resource>({
112140
<FormLabel className="flex flex-col items-start space-y-1.5">
113141
{label}
114142
{hasImage ? null : (
115-
<InputBox>
143+
<InputBox size={size}>
116144
<div className="flex size-full cursor-pointer flex-col items-center justify-center">
117145
<Camera className="text-image-input-icon size-12" />
118146
<span className="text-muted-foreground text-xs">
@@ -123,7 +151,7 @@ export function ImageUpload<T extends Resource>({
123151
)}
124152
</FormLabel>
125153
{hasImage ? (
126-
<InputBox>
154+
<InputBox size={size}>
127155
<FormControl>
128156
<Button
129157
type="button"

src/features/abstract-resource-form/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ export * from "./components/abstract-resource-form";
55
export * from "./hooks/use-arf-sheet";
66

77
export * from "./providers/arf-sheet-provider";
8+
9+
export type { ImageSize } from "./types/inputs";

src/features/abstract-resource-form/types/inputs.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import type {
99
ResourceSchemaKey,
1010
} from "@/features/resources/types";
1111

12+
export type ImageSize = "small" | "medium" | "large" | "wide";
13+
1214
export interface FormInputBase {
1315
label: string;
1416
/** For fields which should only be set on creation, and not in the edit form. */
@@ -51,7 +53,11 @@ type ArrayInputs<T extends Resource> = Partial<
5153

5254
export interface AbstractResourceFormInputs<T extends Resource> {
5355
/** Image upload inputs for image key fields. */
54-
imageInputs?: FormInput<T, z.ZodString, { type: ImageType }>;
56+
imageInputs?: FormInput<
57+
T,
58+
z.ZodString,
59+
{ type: ImageType; size?: ImageSize }
60+
>;
5561
/** Standard text input fields. */
5662
textInputs?: FormInput<T>;
5763
/** Resizable longer text input fields. */

src/features/resources/data/resource-metadata.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ export const RESOURCE_METADATA = {
104104
description: { label: "Opis" },
105105
},
106106
imageInputs: {
107-
coverPhotoKey: { label: "Zdjęcie w tle", type: ImageType.Banner },
107+
coverPhotoKey: {
108+
label: "Zdjęcie w tle",
109+
type: ImageType.Banner,
110+
size: "wide",
111+
},
108112
},
109113
},
110114
defaultValues: {
@@ -481,7 +485,7 @@ export const RESOURCE_METADATA = {
481485
form: {
482486
inputs: {
483487
imageInputs: {
484-
imageKey: { label: "Zdjęcie", type: ImageType.Banner },
488+
imageKey: { label: "Zdjęcie", type: ImageType.Banner, size: "wide" },
485489
},
486490
textInputs: {
487491
title: { label: "Tytuł" },
@@ -771,8 +775,8 @@ export const RESOURCE_METADATA = {
771775
form: {
772776
inputs: {
773777
imageInputs: {
774-
logoKey: { label: "Logo", type: ImageType.Logo },
775-
coverKey: { label: "Baner", type: ImageType.Banner },
778+
logoKey: { label: "Logo", type: ImageType.Logo, size: "small" },
779+
coverKey: { label: "Baner", type: ImageType.Banner, size: "wide" },
776780
},
777781
textInputs: {
778782
name: { label: "Nazwa" },

0 commit comments

Comments
 (0)