Skip to content

Conversation

@Swaim-Sahay
Copy link

@Swaim-Sahay Swaim-Sahay commented Dec 2, 2025

closes #209

What this does

Lets creators show if they're available for work. Shows up as a toggle on their dashboard with 3 options (Available/Busy/Not Looking) and optional custom message.

Brands see a colored badge on creator profiles and can filter search by availability.

Files changed

Frontend:

  • Added AvailabilityToggle component
  • Added AvailabilityBadge component
  • Created CreatorCard with badge
  • Built CreatorSearch page with filter
  • Updated dashboard to show toggle
  • Added route for creator search

Backend:

  • SQL file to add availability columns to users table

Testing done

  • No TS errors
  • Passes linting
  • Tested status changes save correctly
  • Filter works in search
  • Looks good on mobile

Before merging

Run the SQL migration in Backend/add_availability_feature_COMPLETE.sql to add the database columns.

Preview

Screen.Recording.2025-12-02.at.5.57.10.PM.mov

Summary by CodeRabbit

  • New Features
    • Users can set an availability status (available, busy, not_looking) and an optional custom message on their profiles
    • Creator profiles display an availability badge and message preview
    • Brands can search and filter creators by availability on a new "Find Creators" page
    • Dashboard shows an availability toggle for creators
    • Added a scroll-to-top button for improved navigation

✏️ Tip: You can customize this high-level summary in your review settings.

Swaim Sahay added 3 commits November 22, 2025 17:13
- Created ScrollToTop component with smooth animations
- Added circular progress ring showing scroll position
- Gradient purple design with hover effects and tooltip
- Optimized scroll event handling with requestAnimationFrame
- WCAG compliant with proper ARIA attributes
- Responsive and mobile-friendly

Closes AOSSIE-Org#204
- Add requestAnimationFrame throttling for scroll events
- Fix division by zero on non-scrollable pages
- Calculate SVG radius dynamically to match rendered size
- Add proper cleanup and accessibility attributes
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 2, 2025

Warning

Rate limit exceeded

@Swaim-Sahay has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 15 minutes and 29 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between f6a4fe6 and b30dfef.

📒 Files selected for processing (1)
  • Frontend/src/components/CreatorCard.tsx (1 hunks)

Walkthrough

Adds a creator availability feature: DB migration adds availability columns, constraint, index, and comments; frontend adds availability badge, toggle, creator card, search page, scroll-to-top UI, route, and dashboard integration so creators can set status/message and brands can filter/search by availability.

Changes

Cohort / File(s) Summary
Database migrations
Backend/add_availability_feature_COMPLETE.sql, Backend/add_availability_status.sql
Add availability_status (TEXT, default 'available') and availability_message (TEXT, default NULL) to public.users; recreate check_availability_status to allow 'available','busy','not_looking'; create index idx_users_availability; add column comments; backfill NULLs to 'available'.
Availability UI components
Frontend/src/components/AvailabilityBadge.tsx, Frontend/src/components/AvailabilityToggle.tsx
New AvailabilityBadge component (status, icon, colors, optional message). New AvailabilityToggle component that loads/saves availability_status and availability_message via Supabase, provides three-state controls, optional 150-char custom message, preview, loading states, and error handling.
Creator presentation & utilities
Frontend/src/components/CreatorCard.tsx, Frontend/src/components/ui/scroll-to-top.tsx
New CreatorCard shows profile, follower totals, platform icons, and AvailabilityBadge; action button adapts to status. New ScrollToTop floating progress button with scroll progress indicator and smooth scroll behavior.
Brand search page
Frontend/src/pages/Brand/CreatorSearch.tsx
New Brand CreatorSearch page: queries users (id, username, profile_image, category, country, availability_status, availability_message, social_profiles) filtered by role='creator' and availability filter; client-side search by username/category; renders CreatorCard grid with loading/empty states.
App routing & dashboard integration
Frontend/src/App.tsx, Frontend/src/pages/DashboardPage.tsx
Add global ScrollToTop under AuthProvider; new protected route /brand/creatorsCreatorSearch; import and render AvailabilityToggle in Dashboard Overview; add "Find Creators" nav item.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Brand as Browser (Brand UI)
    participant Frontend as Web App (React)
    participant Supabase as Supabase (Postgres)
    Note over Brand,Frontend: Brand searches or views creators
    Brand->>Frontend: Navigate to /brand/creators or set filters
    Frontend->>Supabase: SELECT users WHERE role='creator' + availability filter
    Supabase-->>Frontend: Return creators (incl. availability_status, availability_message, social_profiles)
    Frontend->>Brand: Render CreatorCard grid with AvailabilityBadge
    Note over Brand,Frontend: Creator updates availability from Dashboard
    Brand->>Frontend: Interact with AvailabilityToggle (change status/message)
    Frontend->>Supabase: UPDATE users SET availability_status/message
    Supabase-->>Frontend: OK / Error
    Frontend->>Brand: Update preview & UI or show error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus review on:
    • Frontend/src/components/AvailabilityToggle.tsx — async save logic, error handling, and character-limit enforcement.
    • Frontend/src/pages/Brand/CreatorSearch.tsx — availability filtering logic (especially "all" excluding 'not_looking') and selected fields query shape.
    • DB migrations — idempotency of constraint/index creation, correct backfill, and alignment of allowed status values with frontend.

Suggested reviewers

  • chandansgowda

Poem

🐰 I hopped into code with a cheerful twitch,
Badges, toggles, and search stitched in a stitch.
Creators can flag when they're free or booked,
Brands can find fits without being mistooked.
A tiny hop, a status light — matches take flight! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feature: creator availability status' directly and clearly summarizes the main change—introducing a creator availability feature with status options and messaging.
Linked Issues check ✅ Passed All coding requirements from issue #209 are met: toggle on dashboard (AvailabilityToggle), three status options with custom messaging (AvailabilityToggle + backend columns), availability badge on profiles (AvailabilityBadge in CreatorCard), search/filter functionality (CreatorSearch with availabilityFilter), and non-looking creators excluded from results.
Out of Scope Changes check ✅ Passed All changes directly support the availability feature: database migration adds required columns, frontend components implement required UI, new route/page enable search filtering, and dashboard integration provides the toggle—no unrelated modifications detected.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Swaim-Sahay Swaim-Sahay changed the title Feature/creator availability status Feature: creator availability status Dec 2, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (7)
Backend/add_availability_feature_COMPLETE.sql (1)

31-32: Consider adding a length constraint on availability_message.

The comment documents a 150-character limit, but no database constraint enforces it. If this limit is intentional, add a CHECK constraint or change the column type.

-- Option 1: Add CHECK constraint
ALTER TABLE public.users 
ADD CONSTRAINT check_availability_message_length 
CHECK (char_length(availability_message) <= 150);

-- Option 2: Use VARCHAR instead
ALTER TABLE public.users 
ALTER COLUMN availability_message TYPE VARCHAR(150);
Frontend/src/pages/Brand/CreatorSearch.tsx (3)

63-65: Error handling lacks user feedback.

Errors are only logged to console. Users won't know if the fetch failed. Consider showing an error state or toast notification.

+ const [error, setError] = useState<string | null>(null);
+
  useEffect(() => {
    const loadCreators = async () => {
      setLoading(true);
+     setError(null);
      try {
        // ... existing query logic
      } catch (error) {
        console.error('Error loading creators:', error);
+       setError('Failed to load creators. Please try again.');
      } finally {
        setLoading(false);
      }
    };
    // ...
  }, [availabilityFilter]);

Then render the error state in the UI alongside the loading/empty states.


147-150: Placeholder callback should be implemented or removed.

The onViewProfile callback only logs to console. Either implement navigation to the creator's profile or remove the callback if the feature is not ready.

+ import { useNavigate } from 'react-router-dom';
+
  export default function BrandCreatorSearch() {
+   const navigate = useNavigate();
    // ...
    
    <CreatorCard
      key={creator.id}
      creator={creator}
-     onViewProfile={(id: string) => {
-       // Navigate to creator profile
-       console.log('View profile:', id);
-     }}
+     onViewProfile={(id: string) => navigate(`/basicDetails/${id}`)}
    />

6-19: Consider extracting Creator type to a shared location.

The Creator interface duplicates structure likely used in other components (CreatorCard, AvailabilityToggle). Extracting to a shared types file would improve maintainability.

Create a shared type file:

// Frontend/src/types/creator.ts
export interface Creator {
  id: string;
  username: string;
  profile_image: string | null;
  category: string;
  country: string;
  availability_status: 'available' | 'busy' | 'not_looking';
  availability_message?: string | null;
  social_profiles?: Array<{
    platform: string;
    followers?: number;
    subscriber_count?: number;
  }>;
}
Frontend/src/components/AvailabilityToggle.tsx (2)

161-161: Avoid redundant updates when status hasn't changed.

Clicking the currently selected status button triggers a database update even though nothing has changed. This creates unnecessary network traffic and potential UI flicker.

Apply this diff:

-              onClick={() => updateAvailability(status)}
+              onClick={() => {
+                if (availability.status !== status) {
+                  updateAvailability(status);
+                }
+              }}

200-200: Avoid redundant updates on blur without changes.

The onBlur handler triggers an update every time the textarea loses focus, even if the message hasn't changed since the last save. This creates unnecessary backend calls.

Consider tracking the last saved message and only updating if it differs:

+  const [lastSavedMessage, setLastSavedMessage] = useState('');
+
   // In loadAvailability success path:
+  setLastSavedMessage(data.availability_message || '');
+
   // In updateAvailability success path:
+  setLastSavedMessage(newMessage !== undefined ? newMessage : availability.message);
+
   // In the textarea:
-              onBlur={() => updateAvailability(availability.status, availability.message)}
+              onBlur={() => {
+                if (availability.message !== lastSavedMessage) {
+                  updateAvailability(availability.status, availability.message);
+                }
+              }}
Frontend/src/components/CreatorCard.tsx (1)

102-117: Consider extracting button configuration to reduce duplication.

The availability status is checked twice—once for styling (lines 105-110) and once for the label (lines 112-116). This creates maintenance overhead and potential inconsistency.

Consider this refactor:

+      const buttonConfig = (() => {
+        switch (creator.availability_status) {
+          case 'available':
+            return {
+              className: 'bg-purple-600 hover:bg-purple-700 text-white',
+              label: 'Contact Creator'
+            };
+          case 'busy':
+            return {
+              className: 'bg-yellow-100 hover:bg-yellow-200 text-yellow-700',
+              label: 'View Profile'
+            };
+          default:
+            return {
+              className: 'bg-gray-200 hover:bg-gray-300 text-gray-600',
+              label: 'View Profile Only'
+            };
+        }
+      })();
+
       <button
         onClick={() => onViewProfile?.(creator.id)}
-        className={`w-full py-2 px-4 rounded-lg font-medium transition-colors ${
-          creator.availability_status === 'available'
-            ? 'bg-purple-600 hover:bg-purple-700 text-white'
-            : creator.availability_status === 'busy'
-            ? 'bg-yellow-100 hover:bg-yellow-200 text-yellow-700'
-            : 'bg-gray-200 hover:bg-gray-300 text-gray-600'
-        }`}
+        className={`w-full py-2 px-4 rounded-lg font-medium transition-colors ${buttonConfig.className}`}
       >
-        {creator.availability_status === 'available'
-          ? 'Contact Creator'
-          : creator.availability_status === 'busy'
-          ? 'View Profile'
-          : 'View Profile Only'}
+        {buttonConfig.label}
       </button>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3be437 and 31fa291.

📒 Files selected for processing (9)
  • Backend/add_availability_feature_COMPLETE.sql (1 hunks)
  • Backend/add_availability_status.sql (1 hunks)
  • Frontend/src/App.tsx (3 hunks)
  • Frontend/src/components/AvailabilityBadge.tsx (1 hunks)
  • Frontend/src/components/AvailabilityToggle.tsx (1 hunks)
  • Frontend/src/components/CreatorCard.tsx (1 hunks)
  • Frontend/src/components/ui/scroll-to-top.tsx (1 hunks)
  • Frontend/src/pages/Brand/CreatorSearch.tsx (1 hunks)
  • Frontend/src/pages/DashboardPage.tsx (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
Frontend/src/components/CreatorCard.tsx (1)
Frontend/src/components/AvailabilityBadge.tsx (1)
  • AvailabilityBadge (12-102)
Frontend/src/pages/Brand/CreatorSearch.tsx (2)
Frontend/src/utils/supabase.tsx (1)
  • supabase (11-11)
Frontend/src/components/CreatorCard.tsx (1)
  • CreatorCard (22-121)
Frontend/src/components/AvailabilityToggle.tsx (2)
Frontend/src/context/AuthContext.tsx (1)
  • useAuth (216-222)
Frontend/src/utils/supabase.tsx (1)
  • supabase (11-11)
Frontend/src/App.tsx (1)
Frontend/src/components/ui/scroll-to-top.tsx (1)
  • ScrollToTop (4-134)
Frontend/src/pages/DashboardPage.tsx (1)
Frontend/src/components/AvailabilityToggle.tsx (1)
  • AvailabilityToggle (13-228)
🔇 Additional comments (15)
Frontend/src/components/ui/scroll-to-top.tsx (1)

4-66: Good implementation of scroll-to-top with performance optimizations.

The component correctly uses requestAnimationFrame throttling and passive event listeners for scroll handling. Cleanup on unmount is properly handled. Accessibility attributes are appropriate.

Frontend/src/App.tsx (2)

23-24: LGTM - ScrollToTop and CreatorSearch integration.

The imports and component placement are correct. ScrollToTop is rendered globally inside AuthProvider, and the new /brand/creators route follows the existing protected route pattern.

Also applies to: 50-50


74-78: Route follows established patterns.

The new /brand/creators route is correctly wrapped with ProtectedRoute and follows the existing route structure.

Frontend/src/pages/DashboardPage.tsx (2)

117-120: AvailabilityToggle integration looks correct.

The component is placed appropriately at the top of the Overview tab content. Based on the component summary, it handles its own loading state internally.


42-42: Verify if "Find Creators" link is appropriate for this dashboard.

This dashboard appears to be creator-focused (showing creator metrics like "Total Revenue", "Sponsorships", etc.), but "Find Creators" (/brand/creators) is a brand feature. Confirm whether this link should only appear for brand users, if this dashboard serves both creator and brand roles, or if there's a legitimate cross-role workflow that justifies its presence here.

Frontend/src/pages/Brand/CreatorSearch.tsx (1)

27-71: Data fetching and filtering logic is well-structured.

The implementation correctly:

  • Excludes not_looking creators from search per requirements
  • Uses server-side filtering for availability status
  • Performs client-side filtering for search term (appropriate for reasonable dataset sizes)
  • Properly handles the async function with void loadCreators()
Frontend/src/components/AvailabilityToggle.tsx (3)

90-123: LGTM!

The status configuration mapping is well-structured and provides clear visual feedback for each availability state. The use of semantic colors and icons enhances usability.


125-134: LGTM!

The loading skeleton provides good UX while data is being fetched, preventing layout shift and giving users visual feedback.


72-72: Verify existence of referenced guide file.

The alert messages reference AVAILABILITY_STATUS_GUIDE.md, which may not exist in the repository. This could confuse users who encounter the error. Ensure the guide file exists at the repository root or update the alert message with the correct path to the documentation.

Backend/add_availability_status.sql (2)

1-4: LGTM!

The columns are added safely with IF NOT EXISTS and appropriate defaults. Using TEXT with a constraint is a good pattern, and defaulting to 'available' aligns with the feature requirements.


11-16: LGTM!

The index on availability_status will improve query performance for filtering creators by availability, and the documentation comments provide clear context for future maintainers.

Frontend/src/components/AvailabilityBadge.tsx (1)

1-102: LGTM!

The component is well-structured with:

  • Clear separation of configuration logic (getConfig, getSizeClasses)
  • Proper default cases to handle unexpected values
  • Type-safe props with sensible defaults
  • Responsive size variants
  • Clean, accessible UI with animated pulse effect

The implementation aligns well with the PR objectives for displaying availability badges.

Frontend/src/components/CreatorCard.tsx (3)

23-25: LGTM!

The follower aggregation logic correctly handles both followers and subscriber_count properties, with a sensible fallback to 0. The use of reduce is appropriate here.


52-59: LGTM!

The AvailabilityBadge is well-positioned in the top-right corner of the header with appropriate size and showMessage settings for the card context.


46-46: Verify default avatar asset exists.

The fallback /default-avatar.png assumes a public asset exists at that path. If it doesn't, users will see a broken image icon.

Run the following script to check if the default avatar exists:

#!/bin/bash
# Check for default avatar in public directory
fd -t f "default-avatar.png" public/

If it doesn't exist, consider:

  1. Adding the asset to the public/ directory, or
  2. Using a data URI or SVG placeholder, or
  3. Using a service like ui-avatars.com as a fallback

Comment on lines +14 to +21
-- Step 2: Add validation constraint
-- Drop existing constraint if it exists (in case you're re-running this)
ALTER TABLE public.users DROP CONSTRAINT IF EXISTS check_availability_status;

-- Add the constraint with valid values
ALTER TABLE public.users
ADD CONSTRAINT check_availability_status
CHECK (availability_status IN ('available', 'busy', 'not_looking'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Constraint may fail on existing data with NULL values.

The CHECK constraint is added before the UPDATE that sets NULL values to 'available'. If the table has existing rows, they will have NULL in the new column (PostgreSQL ADD COLUMN with DEFAULT doesn't backfill existing rows in older versions). The constraint will reject NULL values, causing the migration to fail.

Reorder to update before adding the constraint:

 -- Step 1: Add the new columns to users table
 ALTER TABLE public.users 
 ADD COLUMN IF NOT EXISTS availability_status TEXT DEFAULT 'available',
 ADD COLUMN IF NOT EXISTS availability_message TEXT DEFAULT NULL;

--- Step 2: Add validation constraint
--- Drop existing constraint if it exists (in case you're re-running this)
-ALTER TABLE public.users DROP CONSTRAINT IF EXISTS check_availability_status;
-
--- Add the constraint with valid values
-ALTER TABLE public.users 
-ADD CONSTRAINT check_availability_status 
-CHECK (availability_status IN ('available', 'busy', 'not_looking'));
-
--- Step 3: Create index for faster filtering
-CREATE INDEX IF NOT EXISTS idx_users_availability 
-ON public.users(availability_status);
-
--- Step 4: Add helpful comments for documentation
-...
-
--- Step 5: Update existing users to have default availability
+-- Step 2: Update existing users to have default availability (BEFORE adding constraint)
 UPDATE public.users 
 SET availability_status = 'available' 
 WHERE availability_status IS NULL;
+
+-- Step 3: Add validation constraint
+ALTER TABLE public.users DROP CONSTRAINT IF EXISTS check_availability_status;
+ALTER TABLE public.users 
+ADD CONSTRAINT check_availability_status 
+CHECK (availability_status IN ('available', 'busy', 'not_looking'));
+
+-- Step 4: Create index for faster filtering
+CREATE INDEX IF NOT EXISTS idx_users_availability 
+ON public.users(availability_status);

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In Backend/add_availability_feature_COMPLETE.sql around lines 14 to 21, the
CHECK constraint is added before existing NULL values are set to 'available',
which will cause the migration to fail; reorder the steps so you first add the
column (with or without a default), then UPDATE existing rows to set NULL values
to 'available' (or another desired default), and only after existing rows are
backfilled add the CHECK constraint (or replace an interim relaxed constraint
like allowing NULLs with the strict CHECK after backfill). Ensure the migration
updates existing data before enforcing the constraint.

Comment on lines +7 to +9
ALTER TABLE public.users
ADD CONSTRAINT check_availability_status
CHECK (availability_status IN ('available', 'busy', 'not_looking'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

CHECK constraint will fail on re-run.

The ADD CONSTRAINT statement doesn't use IF NOT EXISTS (not supported in standard PostgreSQL for constraints). If this script is executed twice, it will fail with a duplicate constraint error.

Consider using this safer pattern:

 -- Add check constraint to ensure valid status values
-ALTER TABLE public.users 
-ADD CONSTRAINT check_availability_status 
-CHECK (availability_status IN ('available', 'busy', 'not_looking'));
+DO $$ 
+BEGIN
+  IF NOT EXISTS (
+    SELECT 1 FROM pg_constraint 
+    WHERE conname = 'check_availability_status'
+  ) THEN
+    ALTER TABLE public.users 
+    ADD CONSTRAINT check_availability_status 
+    CHECK (availability_status IN ('available', 'busy', 'not_looking'));
+  END IF;
+END $$;

Or use DROP CONSTRAINT IF EXISTS before adding:

ALTER TABLE public.users DROP CONSTRAINT IF EXISTS check_availability_status;
ALTER TABLE public.users ADD CONSTRAINT check_availability_status 
CHECK (availability_status IN ('available', 'busy', 'not_looking'));
🤖 Prompt for AI Agents
In Backend/add_availability_status.sql around lines 7-9, the ALTER TABLE ADD
CONSTRAINT will error on subsequent runs because PostgreSQL has no IF NOT EXISTS
for constraints; modify the script to first remove any existing constraint and
then add it (i.e., perform a DROP CONSTRAINT IF EXISTS for
check_availability_status before the ADD CONSTRAINT), or alternatively guard the
ADD by querying pg_constraint/pg_catalog to only create the constraint when it
does not already exist.

Comment on lines 23 to 57
useEffect(() => {
const loadAvailability = async () => {
try {
const { data, error } = await supabase
.from('users')
.select('availability_status, availability_message')
.eq('id', user?.id)
.single();

if (error) {
console.error('Error loading availability:', error);
// If columns don't exist, just use defaults
setAvailability({ status: 'available', message: '' });
return;
}

if (data) {
setAvailability({
status: data.availability_status || 'available',
message: data.availability_message || ''
});
setShowMessage(!!data.availability_message);
}
} catch (error) {
console.error('Error loading availability:', error);
setAvailability({ status: 'available', message: '' });
} finally {
setLoading(false);
}
};

if (user) {
void loadAvailability();
}
}, [user]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against null user in data fetch.

The useEffect checks if (user) before calling loadAvailability, but the query at lines 26-30 uses user?.id which could still be undefined if user exists but has no id. This would cause a query with eq('id', undefined).

Apply this diff to add an explicit guard:

-    if (user) {
+    if (user?.id) {
       void loadAvailability();
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
const loadAvailability = async () => {
try {
const { data, error } = await supabase
.from('users')
.select('availability_status, availability_message')
.eq('id', user?.id)
.single();
if (error) {
console.error('Error loading availability:', error);
// If columns don't exist, just use defaults
setAvailability({ status: 'available', message: '' });
return;
}
if (data) {
setAvailability({
status: data.availability_status || 'available',
message: data.availability_message || ''
});
setShowMessage(!!data.availability_message);
}
} catch (error) {
console.error('Error loading availability:', error);
setAvailability({ status: 'available', message: '' });
} finally {
setLoading(false);
}
};
if (user) {
void loadAvailability();
}
}, [user]);
useEffect(() => {
const loadAvailability = async () => {
try {
const { data, error } = await supabase
.from('users')
.select('availability_status, availability_message')
.eq('id', user?.id)
.single();
if (error) {
console.error('Error loading availability:', error);
// If columns don't exist, just use defaults
setAvailability({ status: 'available', message: '' });
return;
}
if (data) {
setAvailability({
status: data.availability_status || 'available',
message: data.availability_message || ''
});
setShowMessage(!!data.availability_message);
}
} catch (error) {
console.error('Error loading availability:', error);
setAvailability({ status: 'available', message: '' });
} finally {
setLoading(false);
}
};
if (user?.id) {
void loadAvailability();
}
}, [user]);
🤖 Prompt for AI Agents
In Frontend/src/components/AvailabilityToggle.tsx around lines 23 to 57, the
data fetch uses user?.id which can be undefined even when user exists; guard
explicitly for a valid user.id before running the Supabase query and return
early if missing. Update the useEffect to check if user and user.id are present
(e.g., if (!user || !user.id) { setLoading(false); return; }) before calling
loadAvailability or, inside loadAvailability, validate user.id at the start and
skip the query (setting sensible defaults) when it's absent.

Comment on lines 59 to 88
const updateAvailability = async (newStatus: AvailabilityStatus, newMessage?: string) => {
setSaving(true);
try {
const { error } = await supabase
.from('users')
.update({
availability_status: newStatus,
availability_message: newMessage || availability.message || null
})
.eq('id', user?.id);

if (error) {
console.error('Error updating availability:', error);
alert(`Failed to update availability status.\n\nError: ${error.message}\n\nPlease run the SQL migration in Supabase first. Check AVAILABILITY_STATUS_GUIDE.md for instructions.`);
setSaving(false);
return;
}

setAvailability({
status: newStatus,
message: newMessage !== undefined ? newMessage : availability.message
});
} catch (error) {
console.error('Error updating availability:', error);
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
alert(`Failed to update availability status.\n\nError: ${errorMessage}\n\nPlease run the SQL migration in Supabase first.`);
} finally {
setSaving(false);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against null user in updates.

The updateAvailability function uses user?.id at lines 66 and 68, which could be undefined if the user object exists without an id property, leading to a failed database query.

Apply this diff to add an early return:

 const updateAvailability = async (newStatus: AvailabilityStatus, newMessage?: string) => {
+  if (!user?.id) {
+    console.error('Cannot update availability: user ID is missing');
+    return;
+  }
   setSaving(true);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const updateAvailability = async (newStatus: AvailabilityStatus, newMessage?: string) => {
setSaving(true);
try {
const { error } = await supabase
.from('users')
.update({
availability_status: newStatus,
availability_message: newMessage || availability.message || null
})
.eq('id', user?.id);
if (error) {
console.error('Error updating availability:', error);
alert(`Failed to update availability status.\n\nError: ${error.message}\n\nPlease run the SQL migration in Supabase first. Check AVAILABILITY_STATUS_GUIDE.md for instructions.`);
setSaving(false);
return;
}
setAvailability({
status: newStatus,
message: newMessage !== undefined ? newMessage : availability.message
});
} catch (error) {
console.error('Error updating availability:', error);
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
alert(`Failed to update availability status.\n\nError: ${errorMessage}\n\nPlease run the SQL migration in Supabase first.`);
} finally {
setSaving(false);
}
};
const updateAvailability = async (newStatus: AvailabilityStatus, newMessage?: string) => {
if (!user?.id) {
console.error('Cannot update availability: user ID is missing');
return;
}
setSaving(true);
try {
const { error } = await supabase
.from('users')
.update({
availability_status: newStatus,
availability_message: newMessage || availability.message || null
})
.eq('id', user?.id);
if (error) {
console.error('Error updating availability:', error);
alert(`Failed to update availability status.\n\nError: ${error.message}\n\nPlease run the SQL migration in Supabase first. Check AVAILABILITY_STATUS_GUIDE.md for instructions.`);
setSaving(false);
return;
}
setAvailability({
status: newStatus,
message: newMessage !== undefined ? newMessage : availability.message
});
} catch (error) {
console.error('Error updating availability:', error);
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
alert(`Failed to update availability status.\n\nError: ${errorMessage}\n\nPlease run the SQL migration in Supabase first.`);
} finally {
setSaving(false);
}
};
🤖 Prompt for AI Agents
Frontend/src/components/AvailabilityToggle.tsx around lines 59 to 88: the
updateAvailability function uses user?.id in the DB query which can be undefined
and cause a failed query; add an early guard at the top of the function that
checks if user?.id is falsy and if so logs an error (or alerts), sets saving to
false, and returns immediately to avoid running the supabase update; ensure this
guard is placed before any async calls so the function exits cleanly when there
is no valid user id.

Comment on lines +96 to +115
<circle
cx="50%"
cy="50%"
r="45%"
fill="none"
stroke="rgba(255, 255, 255, 0.2)"
strokeWidth="2"
/>
<circle
cx="50%"
cy="50%"
r="45%"
fill="none"
stroke="white"
strokeWidth="2"
strokeDasharray={circumference}
strokeDashoffset={offset}
strokeLinecap="round"
className="transition-all duration-300"
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

SVG radius mismatch between percentage and pixel calculations.

The circles use r="45%" (percentage-based), but strokeDasharray and strokeDashoffset are calculated using circleRadius derived from getBoundingClientRect() pixel dimensions. This mismatch causes the progress arc to not align correctly with the visible circle.

Use consistent units - either compute the actual pixel radius matching the 45% or use a fixed radius:

- const circumference = 2 * Math.PI * circleRadius;
+ // Match the 45% radius used in the SVG circles
+ const svgSize = svgRef.current?.getBoundingClientRect();
+ const actualRadius = svgSize ? Math.min(svgSize.width, svgSize.height) * 0.45 / 2 : 20;
+ const circumference = 2 * Math.PI * actualRadius;

Alternatively, use a fixed numeric radius in the SVG instead of percentages for simpler calculations.

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
Frontend/src/components/AvailabilityToggle.tsx (2)

62-64: Guard should check user?.id not just user.

The guard condition checks if (user) but the query at line 37 uses user?.id. If user exists without an id, the query would use eq('id', undefined).

This was previously flagged. Apply the suggested fix: if (user?.id).


72-73: Missing guard for user?.id before database update.

The function uses user?.id at line 81 without verifying it exists. If undefined, the update would silently fail or affect no rows.

This was previously flagged. Add an early return: if (!user?.id) { setSaving(false); return; }.

🧹 Nitpick comments (2)
Frontend/src/components/CreatorCard.tsx (2)

92-100: Prefer stable keys over array indices.

Using array indices as React keys can cause issues if the list order changes. Consider using the platform name or a composite key for better stability.

Apply this diff:

-          {creator.social_profiles?.map((profile, idx) => (
+          {creator.social_profiles?.map((profile) => (
             <div
-              key={idx}
+              key={profile.platform}
               className="p-1.5 bg-gray-100 rounded-full text-gray-600"
               title={profile.platform}
             >

104-120: Consider disabling the button when onViewProfile is undefined.

The button is clickable even when onViewProfile is not provided. While optional chaining prevents errors, users experience a non-functional button. Consider conditionally disabling the button or adjusting its appearance.

Example implementation:

<button
  onClick={() => onViewProfile?.(creator.id)}
  disabled={!onViewProfile}
  className={`w-full py-2 px-4 rounded-lg font-medium transition-colors ${
    !onViewProfile 
      ? 'bg-gray-300 text-gray-500 cursor-not-allowed'
      : creator.availability_status === 'available'
      ? 'bg-purple-600 hover:bg-purple-700 text-white'
      : creator.availability_status === 'busy'
      ? 'bg-yellow-100 hover:bg-yellow-200 text-yellow-700'
      : 'bg-gray-200 hover:bg-gray-300 text-gray-600'
  }`}
>
  {/* ... button text ... */}
</button>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 31fa291 and feea541.

📒 Files selected for processing (4)
  • Frontend/src/components/AvailabilityBadge.tsx (1 hunks)
  • Frontend/src/components/AvailabilityToggle.tsx (1 hunks)
  • Frontend/src/components/CreatorCard.tsx (1 hunks)
  • Frontend/src/pages/Brand/CreatorSearch.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • Frontend/src/components/AvailabilityBadge.tsx
  • Frontend/src/pages/Brand/CreatorSearch.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
Frontend/src/components/CreatorCard.tsx (1)
Frontend/src/components/AvailabilityBadge.tsx (1)
  • AvailabilityBadge (19-115)
Frontend/src/components/AvailabilityToggle.tsx (2)
Frontend/src/context/AuthContext.tsx (1)
  • useAuth (216-222)
Frontend/src/utils/supabase.tsx (1)
  • supabase (11-11)
🔇 Additional comments (5)
Frontend/src/components/AvailabilityToggle.tsx (1)

215-222: Textarea auto-save on blur is reasonable, consider potential rapid interactions.

The onBlur handler triggers a save, which works well for auto-save UX. However, if a user changes status while the textarea is focused and then blurs, two near-simultaneous updates could occur. The current implementation handles this acceptably since both updates use the same status value from state at call time.

Frontend/src/components/CreatorCard.tsx (4)

1-2: LGTM!

Clean imports with all dependencies properly referenced in the component.


4-20: LGTM!

The interface is well-structured and correctly typed. The availability_status union type aligns with the three states from the PR objectives, and the social_profiles structure accommodates different platforms with their respective metrics.


27-41: LGTM!

The helper function correctly maps platform names to icons with case-insensitive matching and safely returns null for unsupported platforms.


49-49: Verify the fallback image path exists.

The fallback uses /default-avatar.png, which assumes this asset is in the public root. Ensure this file exists, or consider using a data URI or an asset imported from the src directory to guarantee availability.

Swaim-Sahay and others added 2 commits December 2, 2025 18:19
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@Swaim-Sahay
Copy link
Author

Hi @chandansgowda

Raised a PR here here #210 .Please review and let me know if any further changes required.
Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Creator Availability Status System

1 participant