@@ -2,14 +2,17 @@ import { Card, CardContent, CardHeader } from "@/components/ui/card"
22import { Badge } from "@/components/ui/badge"
33import { Button } from "@/components/ui/button"
44import { Tooltip , TooltipContent , TooltipProvider , TooltipTrigger } from "@/components/ui/tooltip"
5- import { CalendarDays , MapPin , Tag , Share2 , Bookmark , Clock , Users } from "lucide-react"
5+ import { CalendarDays , MapPin , Tag , Share2 , Clock , Users , Bell , Loader2 } from "lucide-react"
66import { cn , formatCurrency } from "@/lib/utils"
77import { DiscountType } from "@/types/enums/discountType" ;
88import { DiscountThumbnailDTO , EventThumbnailDTO } from "@/types/event" ;
99import Image from "next/image" ;
1010import { AspectRatio } from "@/components/ui/aspect-ratio" ;
1111import Link from "next/link" ;
12- import { MouseEvent } from "react" ;
12+ import { MouseEvent , useState , useEffect } from "react" ;
13+ import { toast } from "sonner" ;
14+ import { subscribeToEntity , unsubscribeFromEntity , checkSubscriptionStatus } from "@/lib/subscriptionUtils" ;
15+ import { EventShareDialog } from "./EventShareDialog" ;
1316
1417interface EventCardProps {
1518 event : EventThumbnailDTO
@@ -95,15 +98,70 @@ export function EventCard({ event, className }: EventCardProps) {
9598
9699 const bestDiscount = getBestDiscount ( ) ;
97100
98- // Handler to stop propagation for nested interactive elements
99- const handleButtonClick = ( e : MouseEvent < HTMLButtonElement > ) => {
101+ // State for subscription status and share dialog
102+ const [ isSubscribed , setIsSubscribed ] = useState ( false ) ;
103+ const [ isLoading , setIsLoading ] = useState ( false ) ;
104+ const [ isShareDialogOpen , setIsShareDialogOpen ] = useState ( false ) ;
105+
106+ // Check subscription status on mount
107+ useEffect ( ( ) => {
108+ const checkStatus = async ( ) => {
109+ setIsLoading ( true ) ;
110+ try {
111+ const status = await checkSubscriptionStatus ( event . id , 'event' ) ;
112+ setIsSubscribed ( status ) ;
113+ } catch ( error ) {
114+ console . error ( "Error checking subscription status:" , error ) ;
115+ } finally {
116+ setIsLoading ( false ) ;
117+ }
118+ } ;
119+
120+ checkStatus ( ) ;
121+ } , [ event . id ] ) ;
122+
123+ // Handler for subscribe/unsubscribe action
124+ const handleSubscribeClick = async ( e : MouseEvent < HTMLButtonElement > ) => {
100125 e . stopPropagation ( ) ;
101126 e . preventDefault ( ) ;
102- // Add button-specific logic here (e.g., open share modal, call bookmark API)
103- console . log ( "Button clicked, navigation prevented." ) ;
127+
128+ if ( isLoading ) return ;
129+
130+ setIsLoading ( true ) ;
131+
132+ try {
133+ if ( isSubscribed ) {
134+ // Unsubscribe
135+ const success = await unsubscribeFromEntity ( {
136+ id : event . id ,
137+ type : 'event' ,
138+ name : event . title
139+ } ) ;
140+
141+ if ( success ) {
142+ setIsSubscribed ( false ) ;
143+ toast . success ( `Unsubscribed from ${ event . title } ` ) ;
144+ }
145+ } else {
146+ // Subscribe
147+ const success = await subscribeToEntity ( {
148+ id : event . id ,
149+ type : 'event' ,
150+ name : event . title
151+ } ) ;
152+
153+ if ( success ) {
154+ setIsSubscribed ( true ) ;
155+ toast . success ( `Subscribed to ${ event . title } ` ) ;
156+ }
157+ }
158+ } finally {
159+ setIsLoading ( false ) ;
160+ }
104161 } ;
105162
106163 return (
164+ < >
107165 < Link href = { `/events/${ event . id } ` } className = "block" >
108166 < Card
109167 className = { cn (
@@ -127,18 +185,43 @@ export function EventCard({ event, className }: EventCardProps) {
127185 size = "icon"
128186 variant = "secondary"
129187 className = "bg-background/80 text-foreground backdrop-blur-sm hover:bg-background/95 p-2 h-9 w-9 rounded-full"
130- onClick = { handleButtonClick }
188+ onClick = { ( e ) => {
189+ e . stopPropagation ( ) ;
190+ e . preventDefault ( ) ;
191+ setIsShareDialogOpen ( true ) ;
192+ } }
131193 >
132194 < Share2 className = "w-4 h-4" />
133195 </ Button >
134- < Button
135- size = "icon"
136- variant = "secondary"
137- className = "bg-background/80 text-foreground backdrop-blur-sm hover:bg-background/95 p-2 h-9 w-9 rounded-full"
138- onClick = { handleButtonClick }
139- >
140- < Bookmark className = "w-4 h-4" />
141- </ Button >
196+ < TooltipProvider delayDuration = { 200 } >
197+ < Tooltip >
198+ < TooltipTrigger asChild >
199+ < Button
200+ size = "icon"
201+ variant = "secondary"
202+ disabled = { isLoading }
203+ className = { cn (
204+ "bg-background/80 text-foreground backdrop-blur-sm hover:bg-background/95 p-2 h-9 w-9 rounded-full" ,
205+ isSubscribed && "bg-primary/20 text-primary hover:bg-primary/30"
206+ ) }
207+ onClick = { handleSubscribeClick }
208+ >
209+ { isLoading ? (
210+ < Loader2 className = "w-4 h-4 animate-spin" />
211+ ) : (
212+ < Bell className = "w-4 h-4" />
213+ ) }
214+ </ Button >
215+ </ TooltipTrigger >
216+ < TooltipContent >
217+ { isLoading
218+ ? "Processing..."
219+ : isSubscribed
220+ ? "Unsubscribe from event updates"
221+ : "Subscribe to event updates" }
222+ </ TooltipContent >
223+ </ Tooltip >
224+ </ TooltipProvider >
142225 </ div >
143226 < div className = "absolute top-3 left-3" >
144227 < Badge variant = "secondary" className = "bg-background/80 text-foreground backdrop-blur-sm" >
@@ -212,5 +295,13 @@ export function EventCard({ event, className }: EventCardProps) {
212295 </ CardContent >
213296 </ Card >
214297 </ Link >
298+
299+ { /* Share Dialog */ }
300+ < EventShareDialog
301+ open = { isShareDialogOpen }
302+ onOpenChange = { setIsShareDialogOpen }
303+ event = { event }
304+ />
305+ </ >
215306 )
216307}
0 commit comments