Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement video thumbnail #7

Merged
merged 1 commit into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions admin/components/VideoPlayer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useState } from "react";
import Image from "next/image";
interface VideoPlayerProps {
src: string;
poster: string;
classes: string;
}

const VideoPlayer = ({ src, poster, classes }: VideoPlayerProps) => {
const [loaded, setLoaded] = useState(false);

const handleVideoLoaded = () => {
setLoaded(true);
};

return (
<div className="h-full w-full">
{!loaded && (
<Image
src={poster}
alt="Video Thumbnail"
height={100}
width={100}
className={classes}
/>
)}
<video
src={src}
loop
autoPlay
muted
playsInline
webkit-playsinline
className={`${classes} transition duration-500 ${
loaded ? "opacity-100" : "opacity-0"
}`}
onLoadedData={handleVideoLoaded}
>
Your browser does not support the video tag.
</video>
</div>
);
};

export default VideoPlayer;
115 changes: 103 additions & 12 deletions admin/pages/dishes/add/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import Image from "next/image";
import supabase from "@/utils/supabase";
import { FormEvent, useEffect, useState } from "react";
import { useEffect, useState } from "react";
import { z } from "zod";
import { useRouter } from "next/navigation";
import { TagsInput } from "react-tag-input-component";
Expand Down Expand Up @@ -37,6 +37,17 @@ const AddDishPage = () => {
previewName: string;
}>;

const [thumbnailData, setThumbnail] = useState<any | null>(null);
let thumbnail: string | null = null;
cp-dharti-r marked this conversation as resolved.
Show resolved Hide resolved
const [previewThumbnailData, setPreviewThumbnailData] = useState(
{} as {
previewType: string;
previewUrl: string;
previewName: string;
isDragging: boolean;
}
);

const [videoData, setVideo] = useState<any | null>(null);
let video: string | null = null;
const [previewVideoData, setPreviewVideoData] = useState(
Expand All @@ -63,11 +74,19 @@ const AddDishPage = () => {
images: isImagesChecked
? z.array(z.string().min(10)).min(1, { message: "Image is required" })
: z.null(),
video_thumbnail: isVideoChecked
? z
.string({
required_error: "Video thumbnail is required",
invalid_type_error: "Invalid video thumbnail",
})
.min(10, { message: "Video thumbnail is required" })
: z.null(),
video: isVideoChecked
? z
.string({
required_error: "Video is required",
invalid_type_error: "Video is required",
invalid_type_error: "Invalid video",
})
.min(10, { message: "Video is required" })
: z.null(),
Expand All @@ -94,6 +113,20 @@ const AddDishPage = () => {
}
} else if (videoData) {
const currentDate = new Date();
const { data: imgData, error: imgErr } = await supabase.storage
.from("dishes")
.upload(
currentDate.getTime() + "-" + thumbnailData.name,
thumbnailData
);

if (imgErr) throw imgErr;

thumbnail =
process.env.NEXT_PUBLIC_SUPABASE_STORAGE_URL +
"/dishes/" +
imgData.path;

const { data: videoStore, error: videoErr } = await supabase.storage
.from("dishes")
.upload(currentDate.getTime() + "-" + videoData.name, videoData);
Expand All @@ -113,6 +146,7 @@ const AddDishPage = () => {
tags: tags,
price: price,
images: isVideoChecked ? null : images,
video_thumbnail: thumbnail,
video: video,
});

Expand All @@ -135,6 +169,7 @@ const AddDishPage = () => {
price: price,
description: description,
images: isVideoChecked ? null : images,
video_thumbnail: thumbnail,
video: video,
tags: tags.map((tag) => tag.toLowerCase()),
});
Expand Down Expand Up @@ -189,8 +224,12 @@ const AddDishPage = () => {
setImagesData(files);
};

const handleFileUploading = (file: any) => {
setVideo(file);
const handleThumbnailUploading = (file: any) => {
setThumbnail(file);
};

const handleVideoUploading = (video: any) => {
setVideo(video);
};

return (
Expand Down Expand Up @@ -539,14 +578,67 @@ const AddDishPage = () => {
</MultipleFileUpload>
</div>
) : (
<div>
<div className="flex gap-10">
<SingleImgPreview
accept="image/*"
uploadedFile={[previewThumbnailData, setPreviewThumbnailData]}
callback={handleThumbnailUploading}
>
{!previewThumbnailData || !previewThumbnailData.previewUrl ? (
<div className="relative mb-5.5 flex w-36 h-55 cursor-pointer appearance-none rounded border border-dashed border-primary bg-gray dark:bg-meta-4 items-center justify-center">
<div className="flex flex-col items-center justify-center space-y-3">
<span className="flex h-10 w-10 items-center justify-center rounded-full border border-stroke bg-white dark:border-strokedark dark:bg-boxdark">
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M1.99967 9.33337C2.36786 9.33337 2.66634 9.63185 2.66634 10V12.6667C2.66634 12.8435 2.73658 13.0131 2.8616 13.1381C2.98663 13.2631 3.1562 13.3334 3.33301 13.3334H12.6663C12.8431 13.3334 13.0127 13.2631 13.1377 13.1381C13.2628 13.0131 13.333 12.8435 13.333 12.6667V10C13.333 9.63185 13.6315 9.33337 13.9997 9.33337C14.3679 9.33337 14.6663 9.63185 14.6663 10V12.6667C14.6663 13.1971 14.4556 13.7058 14.0806 14.0809C13.7055 14.456 13.1968 14.6667 12.6663 14.6667H3.33301C2.80257 14.6667 2.29387 14.456 1.91879 14.0809C1.54372 13.7058 1.33301 13.1971 1.33301 12.6667V10C1.33301 9.63185 1.63148 9.33337 1.99967 9.33337Z"
fill="#3C50E0"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7.5286 1.52864C7.78894 1.26829 8.21106 1.26829 8.4714 1.52864L11.8047 4.86197C12.0651 5.12232 12.0651 5.54443 11.8047 5.80478C11.5444 6.06513 11.1223 6.06513 10.8619 5.80478L8 2.94285L5.13807 5.80478C4.87772 6.06513 4.45561 6.06513 4.19526 5.80478C3.93491 5.54443 3.93491 5.12232 4.19526 4.86197L7.5286 1.52864Z"
fill="#3C50E0"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7.99967 1.33337C8.36786 1.33337 8.66634 1.63185 8.66634 2.00004V10C8.66634 10.3682 8.36786 10.6667 7.99967 10.6667C7.63148 10.6667 7.33301 10.3682 7.33301 10V2.00004C7.33301 1.63185 7.63148 1.33337 7.99967 1.33337Z"
fill="#3C50E0"
/>
</svg>
</span>
<p className="text-primary">Click to upload</p>
<p className="text-sm">video thumbnail</p>
<p className="mt-1.5 text-xs">PNG, JPG or JPEG</p>
</div>
</div>
) : (
<div className="flex items-center justify-center">
<Image
className="h-55 w-36 rounded-xl object-cover"
src={previewThumbnailData.previewUrl as string}
height={224}
width={300}
alt="thumbnail-image"
/>
</div>
)}
</SingleImgPreview>
<SingleImgPreview
accept="video/*"
uploadedFile={[previewVideoData, setPreviewVideoData]}
callback={handleFileUploading}
callback={handleVideoUploading}
>
{!previewVideoData || !previewVideoData.previewUrl ? (
<div className="relative block h-55 w-full cursor-pointer appearance-none rounded border border-dashed border-primary bg-gray p-5 dark:bg-meta-4 sm:py-7.5">
<div className="relative flex h-55 w-36 cursor-pointer appearance-none rounded border border-dashed border-primary bg-gray dark:bg-meta-4 items-center justify-center">
<div className="flex flex-col items-center justify-center space-y-3">
<span className="flex h-10 w-10 items-center justify-center rounded-full border border-stroke bg-white dark:border-strokedark dark:bg-boxdark">
<svg
Expand Down Expand Up @@ -576,9 +668,7 @@ const AddDishPage = () => {
/>
</svg>
</span>
<p>
<span className="text-primary">Click to upload</span>
</p>
<p className="text-primary">Click to upload</p>
<p>video for dish</p>
<p className="mt-1.5 text-xs">Video MP4</p>
</div>
Expand All @@ -589,7 +679,7 @@ const AddDishPage = () => {
autoPlay
loop
muted
className="h-55 w-40 object-cover"
className="h-55 w-36 rounded-xl object-cover"
key={previewVideoData.previewUrl}
>
<source
Expand All @@ -604,7 +694,8 @@ const AddDishPage = () => {
)}
<div className="mt-1 text-xs text-meta-1">
{errors.find((error) => error.for === "images")?.message ||
errors.find((error) => error.for === "video")?.message}
errors.find((error) => error.for === "video")?.message ||
errors.find((error) => error.for === "video_thumbnail")?.message}
</div>
<div className="text-end">
<button
Expand Down
Loading
Loading