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
+23 -12
View File
@@ -5,7 +5,7 @@ import { useNavigate } from "react-router-dom";
import { useForm, Controller } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { ArrowLeft, UploadCloud, X, FileVideo, FileText, Image } from "lucide-react";
import { ArrowLeft, UploadCloud, X, FileVideo, FileText, Image, FileAudio } from "lucide-react";
import { useAssets } from "@/contexts/AdminAssetsContext";
import { useAuth } from "@/contexts/AuthContext";
@@ -25,10 +25,11 @@ import {
// ─── Derive file_type from MIME type ──────────────────────────────────────────
function resolveFileType(mimeType = "") {
if (mimeType.startsWith("video/")) return "video";
if (mimeType.startsWith("image/")) return "image";
if (mimeType.startsWith("video/")) return "video";
if (mimeType.startsWith("image/")) return "image";
if (mimeType.startsWith("audio/")) return "audio";
if (mimeType.startsWith("application/") || mimeType.startsWith("text/")) return "document";
return "image";
return "document";
}
// ─── Schema ───────────────────────────────────────────────────────────────────
@@ -45,6 +46,7 @@ const schema = z.object({
function FileTypeIcon({ mimeType = "" }) {
if (mimeType.startsWith("video/")) return <FileVideo className="h-10 w-10 text-blue-400" />;
if (mimeType.startsWith("image/")) return <Image className="h-10 w-10 text-green-400" />;
if (mimeType.startsWith("audio/")) return <FileAudio className="h-10 w-10 text-purple-400" />;
return <FileText className="h-10 w-10 text-orange-400" />;
}
@@ -116,7 +118,7 @@ export default function AddAsset() {
const { uploadAsset, loading } = useAssets();
const { user } = useAuth();
const fileRef = useRef(null);
const fileRef = useRef(null);
const thumbnailRef = useRef(null);
const [thumbKey, setThumbKey] = useState(0);
@@ -135,12 +137,13 @@ export default function AddAsset() {
display_name: "",
description: "",
is_public: "false",
storage_provider: "chibisafe",
storage_provider: "s3", // ← changed from "chibisafe"
},
});
const file = watch("_file");
const isVideo = file?.type?.startsWith("video/");
const isAudio = file?.type?.startsWith("audio/");
// ── Auto-derive file_type from MIME ───────────────────────────────────────
const fileType = file ? resolveFileType(file.type) : null;
@@ -166,6 +169,7 @@ export default function AddAsset() {
hasFileError = true;
}
// Thumbnail is required for video, optional for audio
if (isVideo && !thumbnailRef.current) {
setError("_thumbnail", { message: "A thumbnail is required for video uploads." });
hasFileError = true;
@@ -208,8 +212,8 @@ export default function AddAsset() {
<div className="space-y-1.5">
<Label>File <span className="text-destructive">*</span></Label>
<DropZone
label="Images, videos, documents"
accept="image/*,video/*,application/*,text/*"
label="Images, videos, audio, documents"
accept="image/*,video/*,audio/*,application/*,text/*"
file={fileRef.current}
onFile={setFile}
onClear={() => {
@@ -223,13 +227,19 @@ export default function AddAsset() {
<FieldError message={errors._file?.message} />
</div>
{/* ── Thumbnail (video only) ── */}
{isVideo && (
{/* ── Thumbnail (video required / audio optional) ── */}
{(isVideo || isAudio) && (
<div className="space-y-1.5">
<Label>Thumbnail <span className="text-destructive">*</span></Label>
<Label>
Thumbnail{" "}
{isVideo
? <span className="text-destructive">*</span>
: <span className="text-muted-foreground text-xs">(optional — album / cover art)</span>
}
</Label>
<DropZone
key={thumbKey}
label="JPEG, PNG (video thumbnail)"
label="JPEG, PNG"
accept="image/*"
file={thumbnailRef.current}
onFile={setThumbnail}
@@ -283,6 +293,7 @@ export default function AddAsset() {
<SelectItem value="avatar">Avatar</SelectItem>
<SelectItem value="image">Image</SelectItem>
<SelectItem value="video">Video</SelectItem>
<SelectItem value="audio">Audio</SelectItem>
<SelectItem value="document">Document</SelectItem>
</SelectContent>
</Select>