ready to test

Testing

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-06-22 10:07:20 +08:00
parent 56d984a26a
commit fbef7cb6e6
283 changed files with 25961 additions and 1072 deletions
@@ -0,0 +1,109 @@
// components/generic/CMS/Blocks/TextImageBlock.jsx
import { useState } from "react";
import { ImageIcon } from "lucide-react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { RichTextEditor } from "./TextBlock"; // reuse the shared editor
import { AssetPickerSheet } from "../../AssetPickerSheet";
export function TextImageBlock({ content, onUpdate, blockId, readOnly = false }) {
const [pickerOpen, setPickerOpen] = useState(false);
return (
<div className="space-y-4">
{/* ── Image position ── */}
<div className="space-y-1.5 max-w-[200px]">
<Label>Image Position</Label>
<Select
value={content.image_position ?? "right"}
onValueChange={(v) => onUpdate({ ...content, image_position: v })}
>
<SelectTrigger><SelectValue /></SelectTrigger>
<SelectContent>
<SelectItem value="left">Left</SelectItem>
<SelectItem value="right">Right</SelectItem>
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{/* ── Text side — WYSIWYG ── */}
<div className="space-y-1.5">
<Label>Content</Label>
<RichTextEditor
blockId={`${blockId}_text`}
value={content.body ?? ""}
onChange={(html) => onUpdate({ ...content, body: html })}
/>
</div>
{/* ── Image side ── */}
<div className={[
"space-y-1.5",
content.image_position === "left" ? "md:order-first" : "",
].join(" ")}>
<Label>Image</Label>
{content.url ? (
<div
className="relative rounded-lg overflow-hidden cursor-pointer group"
onClick={() => setPickerOpen(true)}
>
<img
src={content.url}
alt={content.alt ?? ""}
className="w-full aspect-video object-cover"
/>
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
<p className="text-white text-sm font-medium">Change Image</p>
</div>
</div>
) : (
<button
type="button"
onClick={() => setPickerOpen(true)}
className="w-full aspect-video rounded-lg border-2 border-dashed border-muted-foreground/30 hover:border-primary/50 hover:bg-muted/20 transition-colors flex flex-col items-center justify-center gap-2"
>
<ImageIcon className="h-8 w-8 text-muted-foreground/50" />
<p className="text-sm text-muted-foreground">Click to select an image</p>
</button>
)}
{content.url && (
<div className="space-y-1.5">
<Label>Alt Text</Label>
<Input
placeholder="Describe the image..."
value={content.alt ?? ""}
onChange={(e) => onUpdate({ ...content, alt: e.target.value })}
/>
</div>
)}
</div>
</div>
{!readOnly && (
<AssetPickerSheet
open={pickerOpen}
onOpenChange={setPickerOpen}
fileType="image"
onSelect={(asset) => onUpdate({
...content,
asset_id: asset.asset_id,
url: asset.file_url,
})}
/>
)}
</div>
);
}