diff --git a/client/src/App.tsx b/client/src/App.tsx index 8a6f3b6..57750f6 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -4,12 +4,14 @@ import { QueryClientProvider } from "@tanstack/react-query"; import { Toaster } from "@/components/ui/toaster"; import { TooltipProvider } from "@/components/ui/tooltip"; import Home from "@/pages/home"; +import VideoPage from "@/pages/video"; import NotFound from "@/pages/not-found"; function Router() { return ( + ); diff --git a/client/src/components/share-modal.tsx b/client/src/components/share-modal.tsx new file mode 100644 index 0000000..94702a7 --- /dev/null +++ b/client/src/components/share-modal.tsx @@ -0,0 +1,171 @@ +import { useState } from "react"; +import { X, Copy, Facebook, Twitter, Link, Share2 } from "lucide-react"; +import { type Video } from "@shared/schema"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { useToast } from "@/hooks/use-toast"; + +interface ShareModalProps { + video: Video | null; + isOpen: boolean; + onClose: () => void; +} + +export default function ShareModal({ video, isOpen, onClose }: ShareModalProps) { + const [copied, setCopied] = useState(false); + const { toast } = useToast(); + + if (!isOpen || !video) return null; + + // Generate shareable URL + const shareUrl = `${window.location.origin}/video/${video.id}`; + const encodedUrl = encodeURIComponent(shareUrl); + const encodedTitle = encodeURIComponent(video.title); + const encodedDescription = encodeURIComponent(video.description || `Oglej si ta video: ${video.title}`); + + // Social media URLs + const facebookUrl = `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}"e=${encodedTitle}`; + const twitterUrl = `https://twitter.com/intent/tweet?url=${encodedUrl}&text=${encodedTitle}`; + const whatsappUrl = `https://wa.me/?text=${encodedTitle}%20${encodedUrl}`; + + const copyToClipboard = async () => { + try { + await navigator.clipboard.writeText(shareUrl); + setCopied(true); + toast({ + title: "Povezava kopirana!", + description: "Povezava do videa je bila kopirana v odložišče.", + }); + setTimeout(() => setCopied(false), 2000); + } catch (error) { + toast({ + title: "Napaka", + description: "Povezave ni bilo mogoče kopirati.", + variant: "destructive", + }); + } + }; + + const handleBackdropClick = (e: React.MouseEvent) => { + if (e.target === e.currentTarget) { + onClose(); + } + }; + + return ( +
+
+ + +
+
+ +

Deli video

+
+ +
+ {video.title} +
+

+ {video.title} +

+

+ {Math.floor(video.duration / 60)}:{(video.duration % 60).toString().padStart(2, '0')} min +

+
+
+
+ +
+
+ +
+ + +
+
+ +
+ +
+ + + + + +
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/client/src/components/video-card.tsx b/client/src/components/video-card.tsx index 73d9866..6a29da3 100644 --- a/client/src/components/video-card.tsx +++ b/client/src/components/video-card.tsx @@ -1,9 +1,11 @@ -import { Play } from "lucide-react"; +import { Play, Share2 } from "lucide-react"; import { type Video } from "@shared/schema"; +import { Button } from "@/components/ui/button"; interface VideoCardProps { video: Video; onClick: (video: Video) => void; + onShare?: (video: Video) => void; } function formatDuration(seconds: number): string { @@ -39,7 +41,14 @@ function formatDate(date: Date | string): string { return `${Math.floor(diffDays / 30)} month${Math.floor(diffDays / 30) > 1 ? 's' : ''} ago`; } -export default function VideoCard({ video, onClick }: VideoCardProps) { +export default function VideoCard({ video, onClick, onShare }: VideoCardProps) { + + const handleShareClick = (e: React.MouseEvent) => { + e.stopPropagation(); + if (onShare) { + onShare(video); + } + }; return (
+ + {onShare && ( +
+ +
+ )}
@@ -74,13 +97,26 @@ export default function VideoCard({ video, onClick }: VideoCardProps) { > {video.title} -
- - {formatViews(video.views)} - - - {formatDate(video.createdAt)} - +
+
+ + {formatViews(video.views)} + + + {formatDate(video.createdAt)} + +
+ {onShare && ( + + )}
diff --git a/client/src/components/video-grid.tsx b/client/src/components/video-grid.tsx index 4d9a347..48a80e7 100644 --- a/client/src/components/video-grid.tsx +++ b/client/src/components/video-grid.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { type Video } from "@shared/schema"; import VideoCard from "./video-card"; import VideoModal from "./video-modal"; +import ShareModal from "./share-modal"; import { Button } from "@/components/ui/button"; import { ChevronDown } from "lucide-react"; @@ -16,6 +17,8 @@ interface VideoGridProps { export default function VideoGrid({ videos, isLoading, hasMore, onLoadMore, viewMode }: VideoGridProps) { const [selectedVideo, setSelectedVideo] = useState