feat: add ViewCounter enhancements and file upload progress tracking
- Improved `ViewCounter` with visibility-based view increment using `IntersectionObserver` and 50% video progress tracking. - Added real-time file upload progress updates via Socket.io, including status and percentage feedback. - Integrated `ViewCounter` dynamically into `ContentCard` and removed redundant instances from static pages. - Updated backend upload logic to emit progress updates at different stages via the `EventsGateway`.
This commit is contained in:
@@ -10,7 +10,6 @@ import {
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { ViewCounter } from "@/components/view-counter";
|
||||
import { ContentService } from "@/services/content.service";
|
||||
import type { Content } from "@/types/content";
|
||||
|
||||
@@ -46,7 +45,6 @@ export default function MemeModal({
|
||||
</div>
|
||||
) : content ? (
|
||||
<div className="bg-white dark:bg-zinc-900 rounded-lg overflow-hidden">
|
||||
<ViewCounter contentId={content.id} />
|
||||
<ContentCard content={content} />
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -5,7 +5,6 @@ import { notFound } from "next/navigation";
|
||||
import { CommentSection } from "@/components/comment-section";
|
||||
import { ContentCard } from "@/components/content-card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ViewCounter } from "@/components/view-counter";
|
||||
import { ContentService } from "@/services/content.service";
|
||||
|
||||
export const revalidate = 3600; // ISR: Revalider toutes les heures
|
||||
@@ -42,7 +41,6 @@ export default async function MemePage({
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto py-8 px-4">
|
||||
<ViewCounter contentId={content.id} />
|
||||
<Link
|
||||
href="/"
|
||||
className="inline-flex items-center text-sm mb-6 hover:text-primary transition-colors"
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
} from "@/components/ui/select";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { useAuth } from "@/providers/auth-provider";
|
||||
import { useSocket } from "@/providers/socket-provider";
|
||||
import { CategoryService } from "@/services/category.service";
|
||||
import { ContentService } from "@/services/content.service";
|
||||
import type { Category } from "@/types/content";
|
||||
@@ -52,10 +53,32 @@ type UploadFormValues = z.infer<typeof uploadSchema>;
|
||||
export default function UploadPage() {
|
||||
const router = useRouter();
|
||||
const { isAuthenticated, isLoading } = useAuth();
|
||||
const { socket } = useSocket();
|
||||
const [categories, setCategories] = React.useState<Category[]>([]);
|
||||
const [file, setFile] = React.useState<File | null>(null);
|
||||
const [preview, setPreview] = React.useState<string | null>(null);
|
||||
const [isUploading, setIsUploading] = React.useState(false);
|
||||
const [uploadStatus, setUploadStatus] = React.useState<string>("");
|
||||
const [uploadProgress, setUploadProgress] = React.useState<number>(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (socket) {
|
||||
socket.on(
|
||||
"upload_progress",
|
||||
(data: { status: string; progress: number; message?: string }) => {
|
||||
setUploadStatus(data.status);
|
||||
setUploadProgress(data.progress);
|
||||
if (data.status === "error" && data.message) {
|
||||
toast.error(data.message);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return () => {
|
||||
socket.off("upload_progress");
|
||||
};
|
||||
}
|
||||
}, [socket]);
|
||||
|
||||
const form = useForm<UploadFormValues>({
|
||||
resolver: zodResolver(uploadSchema),
|
||||
@@ -327,10 +350,20 @@ export default function UploadPage() {
|
||||
|
||||
<Button type="submit" className="w-full" disabled={isUploading}>
|
||||
{isUploading ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Upload en cours...
|
||||
</>
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
<span>{uploadProgress}%</span>
|
||||
</div>
|
||||
<span className="text-[10px] uppercase tracking-wider opacity-70">
|
||||
{uploadStatus === "starting" && "Initialisation..."}
|
||||
{uploadStatus === "scanning" && "Scan Antivirus..."}
|
||||
{uploadStatus === "processing" && "Optimisation..."}
|
||||
{uploadStatus === "uploading_s3" && "Envoi au cloud..."}
|
||||
{uploadStatus === "saving" && "Finalisation..."}
|
||||
{uploadStatus === "completed" && "Terminé !"}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
"Publier le mème"
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user