Skip to main content

Overview

TechCal uses client-side event tracking through Supabase RPC functions rather than a dedicated REST API endpoint. This approach provides real-time updates and integrates seamlessly with Row Level Security policies.
Event tracking operations are performed client-side using the UserEventService class, which calls Supabase RPC functions with automatic calendar sync.

Authentication

All tracking operations require an authenticated Supabase client session.

Tracking Methods

Toggle Bookmark

Add or remove an event from your bookmarks. Bookmarked events automatically sync to connected calendars. Service Method:
import { UserEventService } from '@/services/userEventService';

const result = await UserEventService.toggleBookmark(userId, eventId);
Parameters:
userId
string
required
UUID of the authenticated user
eventId
string
required
UUID of the event to bookmark/unbookmark
Returns:
{
  isBookmarked: boolean;  // New bookmark state
  wasBookmarked: boolean; // Previous state
  autoBookmarked: boolean; // Whether event was auto-bookmarked
}
Database RPC:
SELECT * FROM toggle_bookmark_v3(
  p_user_id := user_id,
  p_event_id := event_id
);

Set Attendance Status

Update your attendance status for an event. Service Method:
const result = await UserEventService.setAttendanceStatus(
  userId,
  eventId,
  'attending' // or 'attended', 'cancelled'
);
Parameters:
userId
string
required
UUID of the authenticated user
eventId
string
required
UUID of the event
status
string
required
Attendance status to setOptions: attending, attended, cancelled
Returns:
{
  success: boolean;
  status: 'attending' | 'attended' | 'cancelled';
}
Database RPC:
SELECT * FROM set_attendance_status(
  p_user_id := user_id,
  p_event_id := event_id,
  p_status := status
);

Legacy Track Event (Deprecated)

The original trackEvent method is deprecated in favor of decoupled bookmark and attendance operations.
Use toggleBookmark() and setAttendanceStatus() instead for better control and clearer semantics.

Calendar Sync Integration

When you bookmark an event, TechCal automatically syncs it to your connected Google Calendar if:
  1. You’ve connected a Google Calendar account
  2. Calendar sync is enabled in your preferences
  3. The event has valid date/time information
Sync Endpoint:
POST /api/calendar/sync
See Calendar Sync API for details on calendar integration.

Database Schema

Event tracking uses the user_events table with Row Level Security:
CREATE TABLE user_events (
  id UUID PRIMARY KEY,
  user_id UUID REFERENCES profiles(id),
  event_id UUID REFERENCES events(id),
  is_bookmarked BOOLEAN DEFAULT false,
  bookmarked_at TIMESTAMPTZ,
  status TEXT CHECK (status IN ('attending', 'attended', 'cancelled')),
  notes TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(user_id, event_id)
);

Example Usage

React Component Example

'use client';

import { useState } from 'react';
import { UserEventService } from '@/services/userEventService';
import { useAuth } from '@/contexts/AuthContext';

export function BookmarkButton({ eventId }: { eventId: string }) {
  const { user } = useAuth();
  const [isBookmarked, setIsBookmarked] = useState(false);
  const [loading, setLoading] = useState(false);

  const handleToggle = async () => {
    if (!user) return;
    
    setLoading(true);
    try {
      const result = await UserEventService.toggleBookmark(user.id, eventId);
      setIsBookmarked(result.isBookmarked);
      
      if (result.isBookmarked) {
        // Event bookmarked, will auto-sync to calendar
        console.log('Event added to bookmarks');
      }
    } catch (error) {
      console.error('Failed to toggle bookmark:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <button onClick={handleToggle} disabled={loading}>
      {isBookmarked ? 'Remove Bookmark' : 'Bookmark Event'}
    </button>
  );
}

Error Handling

Common errors when tracking events:
Ensure the Supabase client has a valid session before calling tracking methods.
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
  throw new Error('User must be authenticated');
}
The event ID doesn’t exist or has been deleted.
// Verify event exists before tracking
const { data: event } = await supabase
  .from('events')
  .select('id')
  .eq('id', eventId)
  .single();
Calendar sync can fail if the calendar connection expired or was revoked. The bookmark will still be saved, but won’t sync to the external calendar.Check calendar connection status:
GET /api/calendar/google/status

Calendar Sync

Sync events to Google Calendar

Events API

Query and filter events

Build docs developers (and LLMs) love