videofolxtv/client/src/components/video-ads.tsx
sebastjanartic 3714cb7367 Update branding to use a new vibrant red color scheme
Apply the new primary red color #da234d across various UI components, including buttons, loaders, logos, and progress bars, to refresh the platform's visual identity.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 946a0075-7e32-454b-b348-9e7f576d7f45
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/60d372ff-2c10-46c7-b01b-10c3435136b0/946a0075-7e32-454b-b348-9e7f576d7f45/C6hzfGb
2025-09-04 14:30:03 +00:00

126 lines
4.2 KiB
TypeScript

import { useState, useEffect } from "react";
import { useQuery } from "@tanstack/react-query";
import { Card } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { PlayCircle, Clock, Tag, Network } from "lucide-react";
interface VideoAd {
adType: string;
adUrl?: string;
adTitle?: string;
adDuration?: number;
position?: number;
vastTag?: string;
adNetwork?: string;
priority: number;
}
interface VideoAdsProps {
videoId: string;
}
export default function VideoAds({ videoId }: VideoAdsProps) {
const { data, isLoading, error } = useQuery({
queryKey: [`/api/videos/${videoId}/ads`],
});
if (isLoading) {
return (
<Card className="p-6 border-gray-700 bg-gray-800">
<div className="text-center">
<div className="w-10 h-10 bg-[#da234d] rounded-lg flex items-center justify-center shadow-lg animate-pulse mb-3 mx-auto">
<div className="w-0 h-0 border-l-[8px] border-l-white border-y-[6px] border-y-transparent ml-1"></div>
</div>
<div className="text-white text-sm font-medium mb-1">video.folx.tv</div>
<div className="text-gray-400 text-xs">Loading ads...</div>
</div>
</Card>
);
}
if (error) {
return (
<Card className="p-4 border-red-200 bg-red-50">
<p className="text-red-600 text-sm">Failed to load ad metadata</p>
</Card>
);
}
const { ads = [], totalAds = 0 } = (data as any) || {};
if (totalAds === 0) {
return (
<Card className="p-4 border-gray-200 bg-gray-50">
<p className="text-gray-600 text-sm flex items-center gap-2">
<PlayCircle className="w-4 h-4" />
No ad spots configured for this video
</p>
</Card>
);
}
return (
<div className="space-y-3">
<div className="flex items-center gap-2 mb-3">
<PlayCircle className="w-5 h-5 text-blue-600" />
<h3 className="font-semibold text-gray-900">
Video Ads ({totalAds} spots)
</h3>
</div>
{ads.map((ad: VideoAd, index: number) => (
<Card key={index} className="p-4 border border-gray-200 hover:border-blue-300 transition-colors">
<div className="flex items-start justify-between gap-3">
<div className="flex-1">
<div className="flex items-center gap-2 mb-2">
<Badge
variant={ad.adType === 'preroll' ? 'default' : ad.adType === 'postroll' ? 'secondary' : 'outline'}
className="text-xs"
>
{ad.adType.toUpperCase()}
</Badge>
<span className="text-sm font-medium text-gray-900">
{ad.adTitle || `${ad.adType} Advertisement`}
</span>
</div>
<div className="grid grid-cols-2 gap-3 text-sm text-gray-600">
{ad.adDuration && (
<div className="flex items-center gap-1">
<Clock className="w-3 h-3" />
<span>{ad.adDuration}s duration</span>
</div>
)}
{ad.position !== undefined && ad.adType === 'midroll' && (
<div className="flex items-center gap-1">
<PlayCircle className="w-3 h-3" />
<span>At {Math.floor(ad.position / 60)}:{(ad.position % 60).toString().padStart(2, '0')}</span>
</div>
)}
{ad.adNetwork && (
<div className="flex items-center gap-1">
<Network className="w-3 h-3" />
<span>{ad.adNetwork}</span>
</div>
)}
<div className="flex items-center gap-1">
<Tag className="w-3 h-3" />
<span>Priority {ad.priority}</span>
</div>
</div>
{ad.vastTag && (
<div className="mt-2 p-2 bg-gray-50 rounded text-xs font-mono text-gray-700 break-all">
VAST: {ad.vastTag.substring(0, 80)}...
</div>
)}
</div>
</div>
</Card>
))}
</div>
);
}