Refactor forms and uploader components UI with Card layout
Some checks failed
Build and Push Docker Images / changes (push) Successful in 5s
Build and Push Docker Images / build-backend (push) Has been skipped
Build and Push Docker Images / build-frontend (push) Failing after 49s

Updated color, font, and asset forms to use Card and CardContent for improved structure and consistency. Enhanced input styles and hover effects for better user experience. Adjusted the image uploader background for a more cohesive design.
This commit is contained in:
2025-03-13 16:04:54 +01:00
parent 4044d85410
commit 8c1e6b7ebe
3 changed files with 153 additions and 137 deletions

View File

@@ -1,4 +1,4 @@
// src/components/themes/event-theme-assets-uploader.tsx // src/components/event-themes/event-theme-assets-uploader.tsx
"use client"; "use client";
import React, { useState } from "react"; import React, { useState } from "react";
@@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { ImageUploader } from "@/components/ui/image-uploader"; import { ImageUploader } from "@/components/ui/image-uploader";
import { Card, CardContent } from "@/components/ui/card";
interface AssetImage { interface AssetImage {
key: string; key: string;
@@ -76,69 +77,73 @@ export function EventThemeAssetsUploader({
return ( return (
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between mb-3">
<Label className="text-base">Theme Assets</Label> <Label className="text-base font-semibold text-gray-900">
Theme Assets
</Label>
<Button <Button
type="button" type="button"
variant="outline" variant="outline"
size="sm" size="sm"
className="flex items-center gap-1.5 text-sm font-medium"
onClick={handleAddAsset} onClick={handleAddAsset}
> >
<PlusCircle className="h-4 w-4 mr-2" /> <PlusCircle className="h-4 w-4" />
Add Asset Add Asset
</Button> </Button>
</div> </div>
<div className="space-y-4"> <div className="space-y-3">
{assets.map((asset, index) => ( {assets.map((asset, index) => (
<div <Card
key={index} key={index}
className="grid grid-cols-1 md:grid-cols-[1fr,2fr,auto] gap-4 items-start p-4 border rounded-md bg-gray-50" className="overflow-hidden hover:shadow-md transition-shadow"
> >
<div> <CardContent className="grid grid-cols-1 md:grid-cols-[1fr,2fr,auto] gap-4 items-start p-4 pt-4">
<Label htmlFor={`asset-key-${index}`} className="mb-2 block"> <div>
Asset Key <Label
</Label> htmlFor={`asset-key-${index}`}
<Input className="mb-2 block text-sm font-medium text-gray-700"
id={`asset-key-${index}`} >
value={asset.key} Asset Key
onChange={(e) => handleKeyChange(index, e.target.value)} </Label>
placeholder="E.g., 'animal1', 'balloon', etc." <Input
id={`asset-key-${index}`}
value={asset.key}
onChange={(e) => handleKeyChange(index, e.target.value)}
placeholder="E.g., 'animal1', 'balloon', etc."
className="focus:ring-2 focus:ring-primary/20"
/>
</div>
<ImageUploader
id={`asset-url-${index}`}
label="Asset Image"
imageUrl={asset.url}
purpose="theme-asset"
onChange={(url) => handleUrlChange(index, url)}
aspectRatio="square"
maxWidth={400}
maxHeight={400}
/> />
</div>
<ImageUploader <div className="flex items-end h-full pb-2">
id={`asset-url-${index}`} <Button
label="Asset Image" type="button"
imageUrl={asset.url} variant="destructive"
purpose="theme-asset" size="icon"
onChange={(url) => handleUrlChange(index, url)} onClick={() => handleRemoveAsset(index)}
aspectRatio="square" disabled={assets.length === 1}
maxWidth={400} title="Remove Asset"
maxHeight={400} className="hover:bg-red-600/90 transition-colors"
/> >
<Trash2 className="h-4 w-4" />
<div className="flex items-end h-full pb-2"> </Button>
<Button </div>
type="button" </CardContent>
variant="destructive" </Card>
size="icon"
onClick={() => handleRemoveAsset(index)}
disabled={assets.length === 1}
title="Remove Asset"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
))} ))}
</div> </div>
{assets.length === 0 && (
<p className="text-sm text-gray-500 italic">
No assets added. Click &quot;Add Asset&quot; to add theme assets.
</p>
)}
</div> </div>
); );
} }

View File

@@ -327,56 +327,64 @@ export function EventThemeForm({ theme, mode }: ThemeFormProps) {
<div className="grid grid-cols-1 gap-4"> <div className="grid grid-cols-1 gap-4">
{colorInputs.map((input, index) => ( {colorInputs.map((input, index) => (
<div <Card key={index} className="p-0 border overflow-hidden">
key={index} <CardContent className="flex items-center space-x-4 p-3">
className="flex items-center space-x-4 p-3 border rounded-md bg-gray-50" <div className="flex-1">
> <Label
<div className="flex-1"> htmlFor={`color-name-${index}`}
<Label htmlFor={`color-name-${index}`} className="sr-only"> className="sr-only"
Color Name >
</Label> Color Name
<Input </Label>
id={`color-name-${index}`} <Input
value={input.name} id={`color-name-${index}`}
onChange={(e) => value={input.name}
updateColorInput(index, "name", e.target.value) onChange={(e) =>
} updateColorInput(index, "name", e.target.value)
placeholder="Color name (e.g., primary, secondary)" }
/> placeholder="Color name (e.g., primary, secondary)"
</div> />
</div>
<div className="flex-1 flex items-center space-x-2"> <div className="flex-1 flex items-center space-x-2">
<Input <div className="relative w-16 h-10 overflow-hidden rounded-md border border-input">
type="color" <Input
id={`color-value-${index}`} type="color"
value={input.value} id={`color-value-${index}`}
onChange={(e) => value={input.value}
updateColorInput(index, "value", e.target.value) onChange={(e) =>
} updateColorInput(index, "value", e.target.value)
className="w-16 h-10 p-1" }
/> className="absolute inset-0 opacity-0 w-full h-full cursor-pointer"
<Input />
type="text" <div
value={input.value} className="w-full h-full"
onChange={(e) => style={{ backgroundColor: input.value }}
updateColorInput(index, "value", e.target.value) />
} </div>
placeholder="#RRGGBB" <Input
className="flex-1" type="text"
/> value={input.value}
</div> onChange={(e) =>
updateColorInput(index, "value", e.target.value)
}
placeholder="#RRGGBB"
className="flex-1"
/>
</div>
<Button <Button
type="button" type="button"
variant="destructive" variant="destructive"
size="icon" size="icon"
onClick={() => removeColorInput(index)} onClick={() => removeColorInput(index)}
disabled={colorInputs.length <= 1} disabled={colorInputs.length <= 1}
title="Remove Color" title="Remove Color"
> >
<Trash2 className="h-4 w-4" /> <Trash2 className="h-4 w-4" />
</Button> </Button>
</div> </CardContent>
</Card>
))} ))}
</div> </div>
</div> </div>
@@ -398,49 +406,51 @@ export function EventThemeForm({ theme, mode }: ThemeFormProps) {
<div className="grid grid-cols-1 gap-4"> <div className="grid grid-cols-1 gap-4">
{fontInputs.map((input, index) => ( {fontInputs.map((input, index) => (
<div <Card key={index} className="p-0 border overflow-hidden">
key={index} <CardContent className="flex items-center space-x-4 p-3">
className="flex items-center space-x-4 p-3 border rounded-md bg-gray-50" <div className="flex-1">
> <Label htmlFor={`font-name-${index}`} className="sr-only">
<div className="flex-1"> Font Purpose
<Label htmlFor={`font-name-${index}`} className="sr-only"> </Label>
Font Purpose <Input
</Label> id={`font-name-${index}`}
<Input value={input.name}
id={`font-name-${index}`} onChange={(e) =>
value={input.name} updateFontInput(index, "name", e.target.value)
onChange={(e) => }
updateFontInput(index, "name", e.target.value) placeholder="Font purpose (e.g., heading, body)"
} />
placeholder="Font purpose (e.g., heading, body)" </div>
/>
</div>
<div className="flex-1"> <div className="flex-1">
<Label htmlFor={`font-value-${index}`} className="sr-only"> <Label
Font Name htmlFor={`font-value-${index}`}
</Label> className="sr-only"
<Input >
id={`font-value-${index}`} Font Name
value={input.value} </Label>
onChange={(e) => <Input
updateFontInput(index, "value", e.target.value) id={`font-value-${index}`}
} value={input.value}
placeholder="Font name (e.g., Inter, Roboto)" onChange={(e) =>
/> updateFontInput(index, "value", e.target.value)
</div> }
placeholder="Font name (e.g., Inter, Roboto)"
/>
</div>
<Button <Button
type="button" type="button"
variant="destructive" variant="destructive"
size="icon" size="icon"
onClick={() => removeFontInput(index)} onClick={() => removeFontInput(index)}
disabled={fontInputs.length <= 1} disabled={fontInputs.length <= 1}
title="Remove Font" title="Remove Font"
> >
<Trash2 className="h-4 w-4" /> <Trash2 className="h-4 w-4" />
</Button> </Button>
</div> </CardContent>
</Card>
))} ))}
</div> </div>
</div> </div>

View File

@@ -123,7 +123,8 @@ export function ImageUploader({
)} )}
<div <div
className={`relative border-2 border-dashed border-gray-300 rounded-md ${getAspectRatioClass()} overflow-hidden bg-gray-50 hover:bg-gray-100 transition-colors`} className={`relative border-2 border-dashed border-border rounded-md ${getAspectRatioClass()}
overflow-hidden bg-muted/30 hover:bg-muted/50 transition-colors`}
> >
{/* Hidden file input */} {/* Hidden file input */}
<input <input