diff --git a/apps/frontend/src/components/ai/AIChat.tsx b/apps/frontend/src/components/ai/AIChat.tsx
index d4f73a2e..4e5179ef 100644
--- a/apps/frontend/src/components/ai/AIChat.tsx
+++ b/apps/frontend/src/components/ai/AIChat.tsx
@@ -17,6 +17,32 @@ interface AIChatProps {
onUsageUpdate?: () => void;
}
+/**
+ * AI Chat component that provides an interactive chat interface with an AI assistant.
+ * Supports conversation history, model selection, and configurable system prompts.
+ *
+ * @description Interactive chat component for communicating with AI models via OpenRouter.
+ * Features auto-scrolling, message history, loading states, and customizable appearance.
+ *
+ * @param {string} [systemPrompt] - Custom system prompt to override the default AI behavior
+ * @param {string} [placeholder='Type your message...'] - Placeholder text for the input field
+ * @param {string} [className] - Additional CSS classes to apply to the container
+ * @param {boolean} [showModelSelector=false] - Whether to show the AI model selection dropdown
+ * @param {() => void} [onUsageUpdate] - Callback function triggered after each AI response for usage tracking
+ *
+ * @example
+ * // Basic usage
+ *
+ *
+ * @example
+ * // With custom system prompt and model selector
+ * refetchUsage()}
+ * className="h-[600px]"
+ * />
+ */
export function AIChat({
systemPrompt,
placeholder = 'Type your message...',
diff --git a/apps/frontend/src/components/ai/AISettings.tsx b/apps/frontend/src/components/ai/AISettings.tsx
index c0e987a0..31e1100e 100644
--- a/apps/frontend/src/components/ai/AISettings.tsx
+++ b/apps/frontend/src/components/ai/AISettings.tsx
@@ -13,6 +13,25 @@ interface AIConfigForm {
log_conversations: boolean;
}
+/**
+ * AI Settings component for configuring AI integration at the organization level.
+ * Provides controls for enabling/disabling AI, selecting models, adjusting parameters,
+ * and viewing usage statistics.
+ *
+ * @description Administrative panel for managing AI configuration including model selection,
+ * temperature, max tokens, system prompts, and privacy settings. Displays real-time health
+ * status and usage metrics.
+ *
+ * @example
+ * // Basic usage in settings page
+ *
+ *
+ * @example
+ * // Typically used within an admin or settings layout
+ *
+ *
+ *
+ */
export function AISettings() {
const { data: config, isLoading: configLoading } = useAIConfig();
const { data: models } = useAIModels();
diff --git a/apps/frontend/src/components/ai/ChatMessage.tsx b/apps/frontend/src/components/ai/ChatMessage.tsx
index 3102bb40..fe623e02 100644
--- a/apps/frontend/src/components/ai/ChatMessage.tsx
+++ b/apps/frontend/src/components/ai/ChatMessage.tsx
@@ -8,6 +8,42 @@ export interface ChatMessageProps {
isLoading?: boolean;
}
+/**
+ * Chat message component that renders a single message in the AI chat interface.
+ * Supports different visual styles for user, assistant, and system messages.
+ *
+ * @description Displays a chat message with role-specific styling, avatar icons,
+ * and optional timestamp. Handles loading states with animated dots for pending
+ * assistant responses. System messages are rendered as centered badges.
+ *
+ * @param {'user' | 'assistant' | 'system'} role - The role of the message sender
+ * @param {string} content - The text content of the message
+ * @param {Date} [timestamp] - Optional timestamp to display below the message
+ * @param {boolean} [isLoading=false] - Whether to show loading animation instead of content
+ *
+ * @example
+ * // User message
+ *
+ *
+ * @example
+ * // Assistant message with loading state
+ *
+ *
+ * @example
+ * // System message
+ *
+ */
export function ChatMessage({ role, content, timestamp, isLoading }: ChatMessageProps) {
const isUser = role === 'user';
const isSystem = role === 'system';
diff --git a/apps/frontend/src/components/audit/ActivityTimeline.tsx b/apps/frontend/src/components/audit/ActivityTimeline.tsx
index 6beb0d51..66082c96 100644
--- a/apps/frontend/src/components/audit/ActivityTimeline.tsx
+++ b/apps/frontend/src/components/audit/ActivityTimeline.tsx
@@ -15,8 +15,13 @@ import {
} from 'lucide-react';
import clsx from 'clsx';
+/**
+ * Props for the ActivityTimeline component.
+ */
interface ActivityTimelineProps {
+ /** Array of activity logs to display in the timeline */
activities: ActivityLog[];
+ /** Whether the component is in a loading state */
isLoading?: boolean;
}
@@ -46,6 +51,26 @@ const colorMap: Record = {
payment: 'bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400',
};
+/**
+ * Displays a vertical timeline of user activity events.
+ *
+ * @description Renders a chronological list of activity logs with type-specific icons
+ * and color coding. Each activity shows the type label, description, user name,
+ * resource type, relative timestamp, and any associated metadata. Supports loading
+ * state with animated skeleton placeholders.
+ *
+ * @param props - The component props
+ * @param props.activities - Array of activity logs to display in the timeline
+ * @param props.isLoading - Whether to show loading skeleton instead of data
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function ActivityTimeline({ activities, isLoading }: ActivityTimelineProps) {
if (isLoading) {
return (
diff --git a/apps/frontend/src/components/audit/AuditFilters.tsx b/apps/frontend/src/components/audit/AuditFilters.tsx
index 97bed0dc..e8965d00 100644
--- a/apps/frontend/src/components/audit/AuditFilters.tsx
+++ b/apps/frontend/src/components/audit/AuditFilters.tsx
@@ -4,9 +4,15 @@ import { getAuditActionLabel } from '@/hooks/useAudit';
import { Filter, X, Search } from 'lucide-react';
import clsx from 'clsx';
+/**
+ * Props for the AuditFilters component.
+ */
interface AuditFiltersProps {
+ /** Current filter parameters applied to the audit log query */
filters: QueryAuditLogsParams;
+ /** Callback invoked when any filter value changes */
onFiltersChange: (filters: QueryAuditLogsParams) => void;
+ /** List of available entity types for the entity type filter dropdown */
entityTypes?: string[];
}
@@ -21,6 +27,28 @@ const AUDIT_ACTIONS: AuditAction[] = [
'import',
];
+/**
+ * Provides a collapsible filter panel for audit log queries.
+ *
+ * @description Renders a filter interface with controls for action type, entity type,
+ * and date range (from/to). Supports expanding/collapsing the filter panel, displays
+ * active filter count as a badge, and shows removable filter badges when collapsed.
+ * Automatically resets pagination to page 1 when filters change.
+ *
+ * @param props - The component props
+ * @param props.filters - Current filter parameters applied to the audit log query
+ * @param props.onFiltersChange - Callback invoked when any filter value changes
+ * @param props.entityTypes - List of available entity types for the dropdown
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function AuditFilters({ filters, onFiltersChange, entityTypes = [] }: AuditFiltersProps) {
const [isOpen, setIsOpen] = useState(false);
@@ -181,6 +209,16 @@ export function AuditFilters({ filters, onFiltersChange, entityTypes = [] }: Aud
);
}
+/**
+ * Displays a removable badge for an active filter.
+ *
+ * @description Internal component that renders a pill-shaped badge showing
+ * the filter label with a close button to remove the filter.
+ *
+ * @param props - The component props
+ * @param props.label - Text to display in the badge
+ * @param props.onRemove - Callback invoked when the remove button is clicked
+ */
function FilterBadge({ label, onRemove }: { label: string; onRemove: () => void }) {
return (
diff --git a/apps/frontend/src/components/audit/AuditLogRow.tsx b/apps/frontend/src/components/audit/AuditLogRow.tsx
index 5cede424..ba17e5d5 100644
--- a/apps/frontend/src/components/audit/AuditLogRow.tsx
+++ b/apps/frontend/src/components/audit/AuditLogRow.tsx
@@ -4,11 +4,35 @@ import { getAuditActionLabel, getAuditActionColor } from '@/hooks/useAudit';
import { ChevronDown, ChevronRight, User, Clock, Globe, Code } from 'lucide-react';
import clsx from 'clsx';
+/**
+ * Props for the AuditLogRow component.
+ */
interface AuditLogRowProps {
+ /** The audit log entry to display */
log: AuditLog;
+ /** Optional callback invoked when the user clicks to view full details */
onSelect?: (log: AuditLog) => void;
}
+/**
+ * Displays a single audit log entry as an expandable row.
+ *
+ * @description Renders an audit log with summary information (action, entity, user, timestamp)
+ * in a collapsed state. When expanded, shows detailed information including old/new values,
+ * changed fields, metadata, IP address, endpoint, and response status.
+ *
+ * @param props - The component props
+ * @param props.log - The audit log entry to display
+ * @param props.onSelect - Optional callback invoked when the user clicks to view full details
+ *
+ * @example
+ * ```tsx
+ * openDetailModal(log)}
+ * />
+ * ```
+ */
export function AuditLogRow({ log, onSelect }: AuditLogRowProps) {
const [expanded, setExpanded] = useState(false);
diff --git a/apps/frontend/src/components/audit/AuditStatsCard.tsx b/apps/frontend/src/components/audit/AuditStatsCard.tsx
index ae273e2a..93f835d4 100644
--- a/apps/frontend/src/components/audit/AuditStatsCard.tsx
+++ b/apps/frontend/src/components/audit/AuditStatsCard.tsx
@@ -3,11 +3,35 @@ import { getAuditActionLabel, getAuditActionColor } from '@/hooks/useAudit';
import { Activity, TrendingUp, Users, FileText } from 'lucide-react';
import clsx from 'clsx';
+/**
+ * Props for the AuditStatsCard component.
+ */
interface AuditStatsCardProps {
+ /** Aggregated audit statistics including totals, breakdowns by action/entity, and daily trends */
stats: AuditStats;
+ /** Whether the component is in a loading state */
isLoading?: boolean;
}
+/**
+ * Displays an overview card with audit statistics and trends.
+ *
+ * @description Renders a dashboard card showing key audit metrics including total logs,
+ * number of unique actions, entity types, and active users. Also displays breakdowns
+ * by action type and entity type, plus a daily activity trend chart for the last 7 days.
+ *
+ * @param props - The component props
+ * @param props.stats - Aggregated audit statistics object
+ * @param props.isLoading - Whether to show loading skeleton instead of data
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function AuditStatsCard({ stats, isLoading }: AuditStatsCardProps) {
if (isLoading) {
return (
diff --git a/apps/frontend/src/components/commissions/CommissionsDashboard.tsx b/apps/frontend/src/components/commissions/CommissionsDashboard.tsx
index acee82df..b7ce53d7 100644
--- a/apps/frontend/src/components/commissions/CommissionsDashboard.tsx
+++ b/apps/frontend/src/components/commissions/CommissionsDashboard.tsx
@@ -1,12 +1,51 @@
import { DollarSign, Users, Calendar, TrendingUp, Clock, CheckCircle } from 'lucide-react';
import { DashboardSummary, TopEarner, PeriodEarnings } from '../../services/commissions/dashboard.api';
+/**
+ * Props for the CommissionsDashboard component.
+ */
interface CommissionsDashboardProps {
+ /** Summary data containing totals for pending, approved, and paid commissions */
summary: DashboardSummary;
+ /** List of top earning users with their rankings and total earned amounts */
topEarners: TopEarner[];
+ /** List of recent commission periods with their earnings data */
periodEarnings: PeriodEarnings[];
}
+/**
+ * Displays a comprehensive dashboard for commission management.
+ * Shows summary cards with pending, approved, paid commissions and active schemes,
+ * along with top earners ranking and recent period performance.
+ *
+ * @param props - The component props
+ * @param props.summary - Aggregated commission statistics including totals and counts
+ * @param props.topEarners - Ranked list of users by earnings
+ * @param props.periodEarnings - Historical period data with amounts and statuses
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function CommissionsDashboard({ summary, topEarners, periodEarnings }: CommissionsDashboardProps) {
const formatCurrency = (amount: number) =>
new Intl.NumberFormat('en-US', { style: 'currency', currency: summary.currency }).format(amount);
diff --git a/apps/frontend/src/components/commissions/EarningsCard.tsx b/apps/frontend/src/components/commissions/EarningsCard.tsx
index aacff2ad..fe486fb9 100644
--- a/apps/frontend/src/components/commissions/EarningsCard.tsx
+++ b/apps/frontend/src/components/commissions/EarningsCard.tsx
@@ -1,13 +1,45 @@
import { ReactNode } from 'react';
+/**
+ * Props for the EarningsCard component.
+ */
interface EarningsCardProps {
+ /** Title displayed above the value (e.g., "Total Earnings") */
title: string;
+ /** Main value to display (e.g., "$1,500.00") */
value: string;
+ /** Icon element to display on the right side of the card */
icon: ReactNode;
+ /** Color theme for the card styling */
color: 'blue' | 'green' | 'yellow' | 'purple' | 'red';
+ /** Optional subtitle displayed below the value */
subtitle?: string;
}
+/**
+ * Displays a styled card for showing earnings or commission statistics.
+ * Features a title, large value display, colored icon, and optional subtitle.
+ *
+ * @param props - The component props
+ * @param props.title - Label describing the statistic
+ * @param props.value - Formatted value to display prominently
+ * @param props.icon - React node for the icon (e.g., from lucide-react)
+ * @param props.color - Color theme affecting the value text and icon background
+ * @param props.subtitle - Additional context displayed below the value
+ *
+ * @example
+ * ```tsx
+ * import { DollarSign } from 'lucide-react';
+ *
+ * }
+ * color="green"
+ * subtitle="Last 30 days"
+ * />
+ * ```
+ */
export function EarningsCard({ title, value, icon, color, subtitle }: EarningsCardProps) {
const colorClasses = {
blue: 'bg-blue-100 text-blue-600',
diff --git a/apps/frontend/src/components/commissions/EntriesList.tsx b/apps/frontend/src/components/commissions/EntriesList.tsx
index a2dc479b..f4c5fa4e 100644
--- a/apps/frontend/src/components/commissions/EntriesList.tsx
+++ b/apps/frontend/src/components/commissions/EntriesList.tsx
@@ -2,17 +2,60 @@ import { ChevronLeft, ChevronRight } from 'lucide-react';
import { CommissionEntry } from '../../services/commissions/entries.api';
import { EntryStatusBadge } from './EntryStatusBadge';
+/**
+ * Props for the EntriesList component.
+ */
interface EntriesListProps {
+ /** Array of commission entries to display in the table */
entries: CommissionEntry[];
+ /** Total number of entries across all pages */
total: number;
+ /** Current page number (1-indexed) */
page: number;
+ /** Total number of pages available */
totalPages: number;
+ /** Array of selected entry IDs for bulk operations */
selectedEntries: string[];
+ /** Callback when selection changes (for bulk approve/reject) */
onSelectionChange: (ids: string[]) => void;
+ /** Callback when page changes for pagination */
onPageChange: (page: number) => void;
+ /** Callback to refresh the entries list */
onRefresh: () => void;
}
+/**
+ * Displays a paginated table of commission entries with selection support.
+ * Allows selecting pending entries for bulk approval/rejection operations.
+ * Shows entry details including date, user, reference, amounts, and status.
+ *
+ * @param props - The component props
+ * @param props.entries - Commission entries to display
+ * @param props.total - Total entry count for pagination info
+ * @param props.page - Current page number
+ * @param props.totalPages - Total pages for pagination controls
+ * @param props.selectedEntries - Currently selected entry IDs
+ * @param props.onSelectionChange - Handler for selection updates
+ * @param props.onPageChange - Handler for page navigation
+ * @param props.onRefresh - Handler to refresh data after operations
+ *
+ * @example
+ * ```tsx
+ * const [selected, setSelected] = useState([]);
+ * const [page, setPage] = useState(1);
+ *
+ * refetch()}
+ * />
+ * ```
+ */
export function EntriesList({
entries,
total,
diff --git a/apps/frontend/src/components/commissions/EntryStatusBadge.tsx b/apps/frontend/src/components/commissions/EntryStatusBadge.tsx
index 3db198b7..4a4dde23 100644
--- a/apps/frontend/src/components/commissions/EntryStatusBadge.tsx
+++ b/apps/frontend/src/components/commissions/EntryStatusBadge.tsx
@@ -1,9 +1,32 @@
import { EntryStatus } from '../../services/commissions/entries.api';
+/**
+ * Props for the EntryStatusBadge component.
+ */
interface EntryStatusBadgeProps {
+ /** The status of the commission entry */
status: EntryStatus;
}
+/**
+ * Renders a colored badge indicating the status of a commission entry.
+ * Each status has a distinct color for quick visual identification:
+ * - pending: yellow
+ * - approved: green
+ * - rejected: red
+ * - paid: blue
+ * - cancelled: gray
+ *
+ * @param props - The component props
+ * @param props.status - The entry status to display
+ *
+ * @example
+ * ```tsx
+ *
+ *
+ *
+ * ```
+ */
export function EntryStatusBadge({ status }: EntryStatusBadgeProps) {
const getStatusConfig = (status: EntryStatus) => {
switch (status) {
diff --git a/apps/frontend/src/components/commissions/PeriodManager.tsx b/apps/frontend/src/components/commissions/PeriodManager.tsx
index c43f99d4..1b917fcf 100644
--- a/apps/frontend/src/components/commissions/PeriodManager.tsx
+++ b/apps/frontend/src/components/commissions/PeriodManager.tsx
@@ -2,15 +2,53 @@ import { ChevronLeft, ChevronRight, Lock, Unlock, DollarSign, Clock, CheckCircle
import { CommissionPeriod, PeriodStatus } from '../../services/commissions/periods.api';
import { useClosePeriod, useReopenPeriod, useMarkPeriodPaid } from '../../hooks/commissions';
+/**
+ * Props for the PeriodManager component.
+ */
interface PeriodManagerProps {
+ /** Array of commission periods to display */
periods: CommissionPeriod[];
+ /** Total number of periods across all pages */
total: number;
+ /** Current page number (1-indexed) */
page: number;
+ /** Total number of pages available */
totalPages: number;
+ /** Callback when page changes for pagination */
onPageChange: (page: number) => void;
+ /** Callback to refresh the periods list after operations */
onRefresh: () => void;
}
+/**
+ * Manages commission periods with lifecycle operations.
+ * Displays periods in a table with their date ranges, entry counts, and totals.
+ * Provides actions to close, reopen, and mark periods as paid based on status.
+ *
+ * Period lifecycle: open -> closed -> processing -> paid
+ *
+ * @param props - The component props
+ * @param props.periods - Commission periods to display
+ * @param props.total - Total period count for pagination info
+ * @param props.page - Current page number
+ * @param props.totalPages - Total pages for pagination controls
+ * @param props.onPageChange - Handler for page navigation
+ * @param props.onRefresh - Handler to refresh data after operations
+ *
+ * @example
+ * ```tsx
+ * const [page, setPage] = useState(1);
+ *
+ * refetch()}
+ * />
+ * ```
+ */
export function PeriodManager({
periods,
total,
diff --git a/apps/frontend/src/components/commissions/SchemeForm.tsx b/apps/frontend/src/components/commissions/SchemeForm.tsx
index e8504744..03ea41c2 100644
--- a/apps/frontend/src/components/commissions/SchemeForm.tsx
+++ b/apps/frontend/src/components/commissions/SchemeForm.tsx
@@ -3,12 +3,50 @@ import { X, Plus, Trash2 } from 'lucide-react';
import { useCreateScheme, useUpdateScheme } from '../../hooks/commissions';
import { CreateSchemeDto, SchemeType, AppliesTo, TierConfig, CommissionScheme } from '../../services/commissions/schemes.api';
+/**
+ * Props for the SchemeForm component.
+ */
interface SchemeFormProps {
+ /** Existing scheme to edit, or undefined for creating a new scheme */
scheme?: CommissionScheme;
+ /** Callback when the form is closed/cancelled */
onClose: () => void;
+ /** Callback when the scheme is successfully created/updated */
onSuccess: () => void;
}
+/**
+ * Modal form for creating or editing commission schemes.
+ * Supports three scheme types: percentage, fixed amount, and tiered.
+ * Includes configuration for rate, amounts, tiers, application scope, and limits.
+ *
+ * @param props - The component props
+ * @param props.scheme - Existing scheme for editing (omit for create mode)
+ * @param props.onClose - Handler to close the modal
+ * @param props.onSuccess - Handler called after successful save
+ *
+ * @example
+ * ```tsx
+ * // Create mode
+ * setShowForm(false)}
+ * onSuccess={() => {
+ * setShowForm(false);
+ * refetch();
+ * }}
+ * />
+ *
+ * // Edit mode
+ * setShowForm(false)}
+ * onSuccess={() => {
+ * setShowForm(false);
+ * refetch();
+ * }}
+ * />
+ * ```
+ */
export function SchemeForm({ scheme, onClose, onSuccess }: SchemeFormProps) {
const isEditing = !!scheme;
const createMutation = useCreateScheme();
diff --git a/apps/frontend/src/components/commissions/SchemesList.tsx b/apps/frontend/src/components/commissions/SchemesList.tsx
index 2e309894..dda46bab 100644
--- a/apps/frontend/src/components/commissions/SchemesList.tsx
+++ b/apps/frontend/src/components/commissions/SchemesList.tsx
@@ -2,15 +2,51 @@ import { Pencil, Trash2, Copy, ToggleLeft, ToggleRight, ChevronLeft, ChevronRigh
import { CommissionScheme } from '../../services/commissions/schemes.api';
import { useDeleteScheme, useDuplicateScheme, useToggleSchemeActive } from '../../hooks/commissions';
+/**
+ * Props for the SchemesList component.
+ */
interface SchemesListProps {
+ /** Array of commission schemes to display in the table */
schemes: CommissionScheme[];
+ /** Total number of schemes across all pages */
total: number;
+ /** Current page number (1-indexed) */
page: number;
+ /** Total number of pages available */
totalPages: number;
+ /** Callback when page changes for pagination */
onPageChange: (page: number) => void;
+ /** Callback to refresh the schemes list after operations */
onRefresh: () => void;
}
+/**
+ * Displays a paginated table of commission schemes with management actions.
+ * Shows scheme details including name, type, rate/amount, application scope, and status.
+ * Provides actions to toggle active status, duplicate, and delete schemes.
+ *
+ * @param props - The component props
+ * @param props.schemes - Commission schemes to display
+ * @param props.total - Total scheme count for pagination info
+ * @param props.page - Current page number
+ * @param props.totalPages - Total pages for pagination controls
+ * @param props.onPageChange - Handler for page navigation
+ * @param props.onRefresh - Handler to refresh data after operations
+ *
+ * @example
+ * ```tsx
+ * const [page, setPage] = useState(1);
+ *
+ * refetch()}
+ * />
+ * ```
+ */
export function SchemesList({
schemes,
total,
diff --git a/apps/frontend/src/components/feature-flags/FeatureFlagCard.tsx b/apps/frontend/src/components/feature-flags/FeatureFlagCard.tsx
index ccb40d60..6a3af57f 100644
--- a/apps/frontend/src/components/feature-flags/FeatureFlagCard.tsx
+++ b/apps/frontend/src/components/feature-flags/FeatureFlagCard.tsx
@@ -9,14 +9,59 @@ import { MoreVertical, Pencil, Trash2, ToggleLeft, ToggleRight, Copy } from 'luc
import { useState, useRef, useEffect } from 'react';
import clsx from 'clsx';
+/**
+ * Props for the FeatureFlagCard component.
+ */
interface FeatureFlagCardProps {
+ /** The feature flag data to display */
flag: FeatureFlag;
+ /** Callback invoked when the edit action is triggered */
onEdit: (flag: FeatureFlag) => void;
+ /** Callback invoked when the delete action is triggered */
onDelete: (flag: FeatureFlag) => void;
+ /** Callback invoked when the toggle action is triggered */
onToggle: (flag: FeatureFlag) => void;
+ /** Indicates if the toggle operation is in progress */
isToggling?: boolean;
}
+/**
+ * Displays a feature flag as a card with its details, status, and action menu.
+ *
+ * @description Renders a card showing the feature flag's name, key, description,
+ * type, scope, category, rollout percentage, and default value. Includes actions
+ * for toggling, editing, and deleting the flag, plus a copy-to-clipboard button
+ * for the flag key.
+ *
+ * @param props - The component props
+ * @param props.flag - The feature flag data to display
+ * @param props.onEdit - Callback invoked when the edit action is triggered
+ * @param props.onDelete - Callback invoked when the delete action is triggered
+ * @param props.onToggle - Callback invoked when the toggle action is triggered
+ * @param props.isToggling - Indicates if the toggle operation is in progress
+ *
+ * @example
+ * ```tsx
+ * console.log('Edit', flag)}
+ * onDelete={(flag) => console.log('Delete', flag)}
+ * onToggle={(flag) => console.log('Toggle', flag)}
+ * isToggling={false}
+ * />
+ * ```
+ */
export function FeatureFlagCard({
flag,
onEdit,
diff --git a/apps/frontend/src/components/feature-flags/FeatureFlagForm.tsx b/apps/frontend/src/components/feature-flags/FeatureFlagForm.tsx
index 1e978429..d2d0f9c7 100644
--- a/apps/frontend/src/components/feature-flags/FeatureFlagForm.tsx
+++ b/apps/frontend/src/components/feature-flags/FeatureFlagForm.tsx
@@ -2,13 +2,21 @@ import { useState, useEffect } from 'react';
import { FeatureFlag, FlagType, FlagScope, CreateFlagRequest, UpdateFlagRequest } from '@/services/api';
import { Loader2 } from 'lucide-react';
+/**
+ * Props for the FeatureFlagForm component.
+ */
interface FeatureFlagFormProps {
+ /** Existing flag data for editing mode; omit for create mode */
flag?: FeatureFlag;
+ /** Callback invoked on form submission with the flag data */
onSubmit: (data: CreateFlagRequest | UpdateFlagRequest) => void;
+ /** Callback invoked when the cancel button is clicked */
onCancel: () => void;
+ /** Indicates if the submit operation is in progress */
isLoading?: boolean;
}
+/** Available flag types for selection. */
const FLAG_TYPES: { value: FlagType; label: string }[] = [
{ value: 'boolean', label: 'Boolean' },
{ value: 'string', label: 'String' },
@@ -16,6 +24,7 @@ const FLAG_TYPES: { value: FlagType; label: string }[] = [
{ value: 'json', label: 'JSON' },
];
+/** Available flag scopes for selection. */
const FLAG_SCOPES: { value: FlagScope; label: string; description: string }[] = [
{ value: 'global', label: 'Global', description: 'Applies to all tenants and users' },
{ value: 'tenant', label: 'Tenant', description: 'Can be overridden per tenant' },
@@ -23,6 +32,38 @@ const FLAG_SCOPES: { value: FlagScope; label: string; description: string }[] =
{ value: 'plan', label: 'Plan', description: 'Based on subscription plan' },
];
+/**
+ * Form for creating or editing a feature flag.
+ *
+ * @description Renders a form with fields for all feature flag properties including
+ * key (create only), name, description, type, scope, default value, category,
+ * rollout percentage, and enabled status. Validates input and parses the default
+ * value based on the selected flag type.
+ *
+ * @param props - The component props
+ * @param props.flag - Existing flag data for editing mode; omit for create mode
+ * @param props.onSubmit - Callback invoked on form submission with the flag data
+ * @param props.onCancel - Callback invoked when the cancel button is clicked
+ * @param props.isLoading - Indicates if the submit operation is in progress
+ *
+ * @example
+ * ```tsx
+ * // Create mode
+ * createFlag(data)}
+ * onCancel={() => closeModal()}
+ * isLoading={isCreating}
+ * />
+ *
+ * // Edit mode
+ * updateFlag(existingFlag.id, data)}
+ * onCancel={() => closeModal()}
+ * isLoading={isUpdating}
+ * />
+ * ```
+ */
export function FeatureFlagForm({ flag, onSubmit, onCancel, isLoading }: FeatureFlagFormProps) {
const isEditing = !!flag;
diff --git a/apps/frontend/src/components/feature-flags/TenantOverridesPanel.tsx b/apps/frontend/src/components/feature-flags/TenantOverridesPanel.tsx
index a0ecce33..21bd7ee9 100644
--- a/apps/frontend/src/components/feature-flags/TenantOverridesPanel.tsx
+++ b/apps/frontend/src/components/feature-flags/TenantOverridesPanel.tsx
@@ -3,14 +3,53 @@ import { FeatureFlag, TenantFlag } from '@/services/api';
import { Plus, Trash2, ToggleLeft, ToggleRight, AlertCircle } from 'lucide-react';
import clsx from 'clsx';
+/**
+ * Props for the TenantOverridesPanel component.
+ */
interface TenantOverridesPanelProps {
+ /** List of all available feature flags */
flags: FeatureFlag[];
+ /** List of current tenant-specific flag overrides */
overrides: TenantFlag[];
+ /** Callback invoked when adding a new override */
onAdd: (flagId: string, isEnabled: boolean, value?: any) => void;
+ /** Callback invoked when removing an existing override */
onRemove: (flagId: string) => void;
+ /** Indicates if an operation is in progress */
isLoading?: boolean;
}
+/**
+ * Panel for managing tenant-specific feature flag overrides.
+ *
+ * @description Displays a list of tenant overrides with the ability to add new
+ * overrides and remove existing ones. Allows tenants to customize global feature
+ * flag settings for their organization. Only flags that don't already have an
+ * override are available for selection.
+ *
+ * @param props - The component props
+ * @param props.flags - List of all available feature flags
+ * @param props.overrides - List of current tenant-specific flag overrides
+ * @param props.onAdd - Callback invoked when adding a new override
+ * @param props.onRemove - Callback invoked when removing an existing override
+ * @param props.isLoading - Indicates if an operation is in progress
+ *
+ * @example
+ * ```tsx
+ * console.log('Add override', flagId, isEnabled)}
+ * onRemove={(flagId) => console.log('Remove override', flagId)}
+ * isLoading={false}
+ * />
+ * ```
+ */
export function TenantOverridesPanel({
flags,
overrides,
diff --git a/apps/frontend/src/components/notifications/DevicesManager.tsx b/apps/frontend/src/components/notifications/DevicesManager.tsx
index 9bee277c..393dfe3c 100644
--- a/apps/frontend/src/components/notifications/DevicesManager.tsx
+++ b/apps/frontend/src/components/notifications/DevicesManager.tsx
@@ -1,10 +1,35 @@
import React from 'react';
import { useDevices, usePushNotifications, UserDevice } from '@/hooks/usePushNotifications';
+/**
+ * Props for the DevicesManager component.
+ */
interface DevicesManagerProps {
+ /**
+ * Whether to display the header section with title and description.
+ * @default true
+ */
showHeader?: boolean;
}
+/**
+ * Manages user devices registered for push notifications.
+ *
+ * @description Displays a list of devices registered to receive push notifications,
+ * allowing users to view device details, register new devices, and unregister existing ones.
+ * Shows device type icons, activity status, and last used timestamp for each device.
+ *
+ * @param props - The component props
+ * @param props.showHeader - Whether to display the header section with title and "Add device" button
+ *
+ * @example
+ * // Basic usage with header
+ *
+ *
+ * @example
+ * // Without header (for embedding in settings pages)
+ *
+ */
export function DevicesManager({ showHeader = true }: DevicesManagerProps) {
const { data: devices, isLoading, error, refetch } = useDevices();
const { unregisterDevice, isSubscribed, requestPermission, isLoading: pushLoading } = usePushNotifications();
diff --git a/apps/frontend/src/components/notifications/NotificationBell.tsx b/apps/frontend/src/components/notifications/NotificationBell.tsx
index 5f22d425..6a0379f3 100644
--- a/apps/frontend/src/components/notifications/NotificationBell.tsx
+++ b/apps/frontend/src/components/notifications/NotificationBell.tsx
@@ -4,6 +4,28 @@ import clsx from 'clsx';
import { useUnreadNotificationsCount } from '@/hooks/useData';
import { NotificationDrawer } from './NotificationDrawer';
+/**
+ * A bell icon button that displays the unread notification count and opens the notification drawer.
+ *
+ * @description Renders a clickable bell icon that shows a badge with the unread notification count.
+ * When clicked, it opens the NotificationDrawer component as a slide-in panel.
+ * The bell icon color changes based on whether there are unread notifications.
+ *
+ * @example
+ * // Basic usage in a header/navbar
+ *
+ *
+ *
+ *
+ * @example
+ * // Usage in a toolbar
+ *
+ *
+ *
+ *
+ */
export function NotificationBell() {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
const { data } = useUnreadNotificationsCount();
diff --git a/apps/frontend/src/components/notifications/NotificationDrawer.tsx b/apps/frontend/src/components/notifications/NotificationDrawer.tsx
index 86f3c213..04ed9ed0 100644
--- a/apps/frontend/src/components/notifications/NotificationDrawer.tsx
+++ b/apps/frontend/src/components/notifications/NotificationDrawer.tsx
@@ -4,11 +4,41 @@ import clsx from 'clsx';
import { useNotifications, useMarkNotificationAsRead, useMarkAllNotificationsAsRead } from '@/hooks/useData';
import { NotificationItem } from './NotificationItem';
+/**
+ * Props for the NotificationDrawer component.
+ */
interface NotificationDrawerProps {
+ /**
+ * Controls the visibility of the drawer.
+ */
isOpen: boolean;
+ /**
+ * Callback function invoked when the drawer should be closed.
+ */
onClose: () => void;
}
+/**
+ * A slide-in drawer panel that displays user notifications.
+ *
+ * @description Renders a full-height drawer that slides in from the right side of the screen.
+ * Displays a list of notifications with the ability to mark individual or all notifications as read.
+ * Includes a backdrop overlay, loading state, and empty state handling.
+ *
+ * @param props - The component props
+ * @param props.isOpen - Whether the drawer is currently open/visible
+ * @param props.onClose - Callback to close the drawer (triggered by backdrop click or close button)
+ *
+ * @example
+ * // Controlled drawer usage
+ * const [isOpen, setIsOpen] = useState(false);
+ *
+ *
+ * setIsOpen(false)}
+ * />
+ */
export function NotificationDrawer({ isOpen, onClose }: NotificationDrawerProps) {
const navigate = useNavigate();
const { data, isLoading } = useNotifications(1, 20);
diff --git a/apps/frontend/src/components/notifications/NotificationItem.tsx b/apps/frontend/src/components/notifications/NotificationItem.tsx
index da822f08..67ed7d05 100644
--- a/apps/frontend/src/components/notifications/NotificationItem.tsx
+++ b/apps/frontend/src/components/notifications/NotificationItem.tsx
@@ -3,9 +3,24 @@ import { Bell, AlertCircle, CheckCircle, Info, AlertTriangle } from 'lucide-reac
import clsx from 'clsx';
import type { Notification } from '@/hooks/useData';
+/**
+ * Props for the NotificationItem component.
+ */
interface NotificationItemProps {
+ /**
+ * The notification object to display.
+ */
notification: Notification;
+ /**
+ * Callback invoked when the notification is clicked to mark it as read.
+ * @param id - The notification ID
+ */
onRead: (id: string) => void;
+ /**
+ * Optional callback invoked when the notification has an action URL.
+ * If provided and the notification has an action_url, navigation will occur.
+ * @param url - The URL to navigate to
+ */
onNavigate?: (url: string) => void;
}
@@ -25,6 +40,33 @@ const typeColors: Record = {
default: 'text-secondary-500 bg-secondary-50 dark:bg-secondary-800',
};
+/**
+ * Renders a single notification item with icon, title, message, and timestamp.
+ *
+ * @description Displays a notification with type-based icon and coloring (info, success, warning, error).
+ * Shows read/unread status visually and handles click events to mark as read and optionally navigate.
+ * Uses relative time formatting for the timestamp (e.g., "5 minutes ago").
+ *
+ * @param props - The component props
+ * @param props.notification - The notification data including id, title, message, type, and timestamps
+ * @param props.onRead - Callback to mark the notification as read when clicked
+ * @param props.onNavigate - Optional callback for navigation when notification has an action URL
+ *
+ * @example
+ * // Basic usage
+ * markAsRead(id)}
+ * onNavigate={(url) => navigate(url)}
+ * />
+ */
export function NotificationItem({ notification, onRead, onNavigate }: NotificationItemProps) {
const isRead = !!notification.read_at;
const Icon = typeIcons[notification.type] || typeIcons.default;
diff --git a/apps/frontend/src/components/notifications/PushPermissionBanner.tsx b/apps/frontend/src/components/notifications/PushPermissionBanner.tsx
index 88e40a59..16864b9e 100644
--- a/apps/frontend/src/components/notifications/PushPermissionBanner.tsx
+++ b/apps/frontend/src/components/notifications/PushPermissionBanner.tsx
@@ -1,10 +1,43 @@
import React from 'react';
import { usePushNotifications } from '@/hooks/usePushNotifications';
+/**
+ * Props for the PushPermissionBanner component.
+ */
interface PushPermissionBannerProps {
+ /**
+ * Optional callback invoked when the user dismisses the banner.
+ * The dismissal is also persisted to localStorage.
+ */
onDismiss?: () => void;
}
+/**
+ * A promotional banner prompting users to enable push notifications.
+ *
+ * @description Displays a banner encouraging users to enable browser push notifications.
+ * Automatically hides when: push notifications are not supported, already subscribed,
+ * permission was denied, or the banner was previously dismissed. Stores dismissal
+ * state in localStorage to avoid showing repeatedly.
+ *
+ * @param props - The component props
+ * @param props.onDismiss - Optional callback when user dismisses the banner (via "Not now" or close button)
+ *
+ * @example
+ * // Basic usage at the top of a dashboard
+ *
+ *
+ *
+ *
+ *
+ * @example
+ * // With custom dismiss handling
+ * {
+ * analytics.track('push_banner_dismissed');
+ * }}
+ * />
+ */
export function PushPermissionBanner({ onDismiss }: PushPermissionBannerProps) {
const {
isSupported,
diff --git a/apps/frontend/src/components/sales/ActivityForm.tsx b/apps/frontend/src/components/sales/ActivityForm.tsx
index e6a26589..8e5b8538 100644
--- a/apps/frontend/src/components/sales/ActivityForm.tsx
+++ b/apps/frontend/src/components/sales/ActivityForm.tsx
@@ -3,12 +3,45 @@ import { X } from 'lucide-react';
import { useCreateActivity } from '../../hooks/sales';
import { CreateActivityDto, ActivityType } from '../../services/sales/activities.api';
+/**
+ * Props for the ActivityForm component
+ */
interface ActivityFormProps {
+ /** Optional lead ID to associate the activity with */
leadId?: string;
+ /** Optional opportunity ID to associate the activity with */
opportunityId?: string;
+ /** Callback function triggered when the form is closed or after successful submission */
onClose: () => void;
}
+/**
+ * Modal form component for creating sales activities such as calls, meetings, tasks, emails, or notes.
+ * Provides fields for activity type, subject, description, due date, and duration.
+ * Shows conditional fields based on activity type (e.g., call direction for calls, location for meetings).
+ * Activities can be associated with a lead, opportunity, or both.
+ *
+ * @param props - The component props
+ * @param props.leadId - Optional lead ID to link the activity
+ * @param props.opportunityId - Optional opportunity ID to link the activity
+ * @param props.onClose - Callback to close the modal
+ * @returns A modal form for activity creation
+ *
+ * @example
+ * ```tsx
+ * // Activity for a lead
+ * setShowForm(false)}
+ * />
+ *
+ * // Activity for an opportunity
+ * setShowForm(false)}
+ * />
+ * ```
+ */
export function ActivityForm({ leadId, opportunityId, onClose }: ActivityFormProps) {
const [formData, setFormData] = useState({
type: 'task',
diff --git a/apps/frontend/src/components/sales/ActivityTimeline.tsx b/apps/frontend/src/components/sales/ActivityTimeline.tsx
index e547c91e..47983048 100644
--- a/apps/frontend/src/components/sales/ActivityTimeline.tsx
+++ b/apps/frontend/src/components/sales/ActivityTimeline.tsx
@@ -1,10 +1,48 @@
import { Phone, Users, CheckSquare, Mail, FileText, Clock, CheckCircle } from 'lucide-react';
import { Activity, ActivityType, ActivityStatus } from '../../services/sales/activities.api';
+/**
+ * Props for the ActivityTimeline component
+ */
interface ActivityTimelineProps {
+ /** Array of activity objects to display in chronological order */
activities: Activity[];
}
+/**
+ * Displays a vertical timeline of sales activities with visual differentiation by type.
+ * Each activity shows an icon based on type (call, meeting, task, email, note),
+ * subject, description, status indicator, date, and optional outcome.
+ * Uses color-coded icons and a connecting timeline line for visual hierarchy.
+ *
+ * @param props - The component props
+ * @param props.activities - Array of activities to display in the timeline
+ * @returns A timeline component showing activity history
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function ActivityTimeline({ activities }: ActivityTimelineProps) {
const getIcon = (type: ActivityType) => {
switch (type) {
diff --git a/apps/frontend/src/components/sales/ConversionFunnel.tsx b/apps/frontend/src/components/sales/ConversionFunnel.tsx
index a64dbf42..09ff8efa 100644
--- a/apps/frontend/src/components/sales/ConversionFunnel.tsx
+++ b/apps/frontend/src/components/sales/ConversionFunnel.tsx
@@ -1,9 +1,37 @@
import { ConversionRates } from '../../services/sales/dashboard.api';
+/**
+ * Props for the ConversionFunnel component
+ */
interface ConversionFunnelProps {
+ /** Conversion rate data including stage-to-stage rates and breakdown by source */
conversion: ConversionRates;
}
+/**
+ * Displays a visual sales conversion funnel with stage breakdown and rates.
+ * Shows a tapered funnel visualization from Leads to Opportunities to Won deals.
+ * Includes conversion rate metrics and optional breakdown by lead source.
+ *
+ * @param props - The component props
+ * @param props.conversion - Conversion rate data for funnel visualization
+ * @returns A funnel chart component with conversion metrics
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function ConversionFunnel({ conversion }: ConversionFunnelProps) {
const funnelStages = [
{ name: 'Leads', value: 100, color: 'bg-blue-500' },
diff --git a/apps/frontend/src/components/sales/LeadCard.tsx b/apps/frontend/src/components/sales/LeadCard.tsx
index f665afec..21530017 100644
--- a/apps/frontend/src/components/sales/LeadCard.tsx
+++ b/apps/frontend/src/components/sales/LeadCard.tsx
@@ -1,10 +1,39 @@
import { Lead } from '../../services/sales/leads.api';
import { Mail, Phone, Building, Briefcase, Globe, MapPin, Star } from 'lucide-react';
+/**
+ * Props for the LeadCard component
+ */
interface LeadCardProps {
+ /** The lead data object to display */
lead: Lead;
}
+/**
+ * Displays detailed information about a sales lead in a card format.
+ * Shows contact information, company details, address, lead status, source, and score.
+ *
+ * @param props - The component props
+ * @param props.lead - The lead data object containing all lead information
+ * @returns A card component displaying the lead's complete details
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function LeadCard({ lead }: LeadCardProps) {
const getStatusColor = (status: string) => {
switch (status) {
diff --git a/apps/frontend/src/components/sales/LeadForm.tsx b/apps/frontend/src/components/sales/LeadForm.tsx
index e3cf1ae0..b3dd5d7d 100644
--- a/apps/frontend/src/components/sales/LeadForm.tsx
+++ b/apps/frontend/src/components/sales/LeadForm.tsx
@@ -3,11 +3,38 @@ import { X } from 'lucide-react';
import { useCreateLead, useUpdateLead } from '../../hooks/sales';
import { Lead, CreateLeadDto, LeadSource, LeadStatus } from '../../services/sales/leads.api';
+/**
+ * Props for the LeadForm component
+ */
interface LeadFormProps {
+ /** Optional existing lead data for edit mode. If not provided, form operates in create mode */
lead?: Lead;
+ /** Callback function triggered when the form is closed or after successful submission */
onClose: () => void;
}
+/**
+ * Modal form component for creating or editing sales leads.
+ * Provides fields for lead contact information, company details, source, status, and notes.
+ * Handles form validation and submission via React Query mutations.
+ *
+ * @param props - The component props
+ * @param props.lead - Optional existing lead data for editing
+ * @param props.onClose - Callback to close the modal
+ * @returns A modal form for lead creation/editing
+ *
+ * @example
+ * ```tsx
+ * // Create mode
+ * setShowForm(false)} />
+ *
+ * // Edit mode
+ * setShowForm(false)}
+ * />
+ * ```
+ */
export function LeadForm({ lead, onClose }: LeadFormProps) {
const [formData, setFormData] = useState({
first_name: lead?.first_name || '',
diff --git a/apps/frontend/src/components/sales/LeadsList.tsx b/apps/frontend/src/components/sales/LeadsList.tsx
index 4e60024d..550a3c26 100644
--- a/apps/frontend/src/components/sales/LeadsList.tsx
+++ b/apps/frontend/src/components/sales/LeadsList.tsx
@@ -1,14 +1,46 @@
import { useNavigate } from 'react-router-dom';
import { Lead } from '../../services/sales/leads.api';
+/**
+ * Props for the LeadsList component
+ */
interface LeadsListProps {
+ /** Array of lead objects to display in the table */
leads: Lead[];
+ /** Total number of leads across all pages */
total: number;
+ /** Current page number (1-indexed) */
page: number;
+ /** Total number of available pages */
totalPages: number;
+ /** Callback function triggered when user navigates to a different page */
onPageChange: (page: number) => void;
}
+/**
+ * Displays a paginated table of sales leads with navigation support.
+ * Shows lead name, company, status, source, score, and creation date.
+ * Clicking a row navigates to the lead detail page.
+ *
+ * @param props - The component props
+ * @param props.leads - Array of leads to display
+ * @param props.total - Total lead count for pagination info
+ * @param props.page - Current page number
+ * @param props.totalPages - Total pages available
+ * @param props.onPageChange - Page navigation callback
+ * @returns A table component with pagination controls
+ *
+ * @example
+ * ```tsx
+ * setCurrentPage(newPage)}
+ * />
+ * ```
+ */
export function LeadsList({ leads, total, page, totalPages, onPageChange }: LeadsListProps) {
const navigate = useNavigate();
diff --git a/apps/frontend/src/components/sales/OpportunityCard.tsx b/apps/frontend/src/components/sales/OpportunityCard.tsx
index 0b1389ee..aa529a3a 100644
--- a/apps/frontend/src/components/sales/OpportunityCard.tsx
+++ b/apps/frontend/src/components/sales/OpportunityCard.tsx
@@ -1,12 +1,45 @@
import { DollarSign, Calendar, User } from 'lucide-react';
import { Opportunity } from '../../services/sales/opportunities.api';
+/**
+ * Props for the OpportunityCard component
+ */
interface OpportunityCardProps {
+ /** The opportunity data object to display */
opportunity: Opportunity;
+ /** Whether to render in compact mode with minimal information. Defaults to false */
compact?: boolean;
+ /** Optional click handler for card interaction */
onClick?: () => void;
}
+/**
+ * Displays a sales opportunity in a card format with two display modes.
+ * Full mode shows name, company, amount, probability, close date, and contact.
+ * Compact mode shows only name and amount for use in dense layouts like pipeline boards.
+ *
+ * @param props - The component props
+ * @param props.opportunity - The opportunity data to display
+ * @param props.compact - Enable compact display mode
+ * @param props.onClick - Click handler for card interaction
+ * @returns A card component displaying opportunity information
+ *
+ * @example
+ * ```tsx
+ * // Full display mode
+ * navigate(`/opportunities/${opportunityData.id}`)}
+ * />
+ *
+ * // Compact mode for pipeline boards
+ * handleSelect(opportunityData)}
+ * />
+ * ```
+ */
export function OpportunityCard({ opportunity, compact = false, onClick }: OpportunityCardProps) {
const formatCurrency = (amount: number) => {
return new Intl.NumberFormat('en-US', {
diff --git a/apps/frontend/src/components/sales/OpportunityForm.tsx b/apps/frontend/src/components/sales/OpportunityForm.tsx
index 588925c0..97875b69 100644
--- a/apps/frontend/src/components/sales/OpportunityForm.tsx
+++ b/apps/frontend/src/components/sales/OpportunityForm.tsx
@@ -3,11 +3,39 @@ import { X } from 'lucide-react';
import { useCreateOpportunity, useUpdateOpportunity } from '../../hooks/sales';
import { Opportunity, CreateOpportunityDto, OpportunityStage } from '../../services/sales/opportunities.api';
+/**
+ * Props for the OpportunityForm component
+ */
interface OpportunityFormProps {
+ /** Optional existing opportunity data for edit mode. If not provided, form operates in create mode */
opportunity?: Opportunity;
+ /** Callback function triggered when the form is closed or after successful submission */
onClose: () => void;
}
+/**
+ * Modal form component for creating or editing sales opportunities.
+ * Provides fields for opportunity name, amount, currency, probability, stage,
+ * expected close date, contact information, and notes.
+ * Handles form validation and submission via React Query mutations.
+ *
+ * @param props - The component props
+ * @param props.opportunity - Optional existing opportunity data for editing
+ * @param props.onClose - Callback to close the modal
+ * @returns A modal form for opportunity creation/editing
+ *
+ * @example
+ * ```tsx
+ * // Create mode
+ * setShowForm(false)} />
+ *
+ * // Edit mode
+ * setShowForm(false)}
+ * />
+ * ```
+ */
export function OpportunityForm({ opportunity, onClose }: OpportunityFormProps) {
const [formData, setFormData] = useState({
name: opportunity?.name || '',
diff --git a/apps/frontend/src/components/sales/PipelineBoard.tsx b/apps/frontend/src/components/sales/PipelineBoard.tsx
index 8a479df4..89cc63f8 100644
--- a/apps/frontend/src/components/sales/PipelineBoard.tsx
+++ b/apps/frontend/src/components/sales/PipelineBoard.tsx
@@ -2,10 +2,40 @@ import { useNavigate } from 'react-router-dom';
import { PipelineView } from '../../services/sales/opportunities.api';
import { OpportunityCard } from './OpportunityCard';
+/**
+ * Props for the PipelineBoard component
+ */
interface PipelineBoardProps {
+ /** Array of pipeline stages with their opportunities, counts, and totals */
stages: PipelineView[];
}
+/**
+ * Displays a Kanban-style sales pipeline board with opportunities organized by stage.
+ * Open stages (prospecting, qualification, proposal, negotiation) are shown as columns.
+ * Closed stages (won/lost) are displayed in a separate grid below.
+ * Each column shows stage name, opportunity count, and total value.
+ *
+ * @param props - The component props
+ * @param props.stages - Array of pipeline stage data with opportunities
+ * @returns A Kanban board component for visualizing the sales pipeline
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function PipelineBoard({ stages }: PipelineBoardProps) {
const navigate = useNavigate();
diff --git a/apps/frontend/src/components/sales/SalesDashboard.tsx b/apps/frontend/src/components/sales/SalesDashboard.tsx
index d614a8c4..319e41b9 100644
--- a/apps/frontend/src/components/sales/SalesDashboard.tsx
+++ b/apps/frontend/src/components/sales/SalesDashboard.tsx
@@ -2,11 +2,44 @@ import { TrendingUp, Users, DollarSign, Target, ArrowUpRight, ArrowDownRight } f
import { SalesSummary, ConversionRates } from '../../services/sales/dashboard.api';
import { ConversionFunnel } from './ConversionFunnel';
+/**
+ * Props for the SalesDashboard component
+ */
interface SalesDashboardProps {
+ /** Sales summary data including leads, opportunities, pipeline, and activities metrics */
summary: SalesSummary;
+ /** Conversion rate data for the sales funnel visualization */
conversion: ConversionRates;
}
+/**
+ * Displays a comprehensive sales dashboard with key metrics and visualizations.
+ * Includes stat cards for total leads, open opportunities, won value, and win rate.
+ * Shows pipeline breakdown by stage, conversion funnel, and activities overview.
+ *
+ * @param props - The component props
+ * @param props.summary - Sales summary metrics data
+ * @param props.conversion - Conversion rates for funnel visualization
+ * @returns A dashboard component with sales KPIs and charts
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
export function SalesDashboard({ summary, conversion }: SalesDashboardProps) {
const formatCurrency = (amount: number) => {
return new Intl.NumberFormat('en-US', {
diff --git a/apps/frontend/src/components/storage/FileItem.tsx b/apps/frontend/src/components/storage/FileItem.tsx
index 33af2244..c5f6ee50 100644
--- a/apps/frontend/src/components/storage/FileItem.tsx
+++ b/apps/frontend/src/components/storage/FileItem.tsx
@@ -15,10 +15,17 @@ import {
import { StorageFile, storageApi } from '@/services/api';
import { useDeleteFile } from '@/hooks/useStorage';
+/**
+ * Props for the FileItem component.
+ */
interface FileItemProps {
+ /** The storage file object containing metadata and content info */
file: StorageFile;
+ /** Display mode: 'grid' for thumbnail cards, 'list' for horizontal rows */
view?: 'grid' | 'list';
+ /** Callback fired after successful file deletion */
onDelete?: () => void;
+ /** Callback fired when user requests file preview (images only) */
onPreview?: (file: StorageFile) => void;
}
@@ -56,6 +63,32 @@ function VisibilityIcon({ visibility }: { visibility: string }) {
}
}
+/**
+ * Displays a single file entry with download, delete, and preview actions.
+ * Supports both grid (thumbnail cards) and list (horizontal rows) view modes.
+ * Automatically shows appropriate icons based on file MIME type and handles
+ * visibility indicators (private, tenant, public).
+ *
+ * @description Renders a file item with actions for download, delete, and preview.
+ * @param props - The component props
+ * @param props.file - The storage file object to display
+ * @param props.view - Display mode: 'grid' or 'list' (default: 'list')
+ * @param props.onDelete - Optional callback after successful deletion
+ * @param props.onPreview - Optional callback for image preview requests
+ *
+ * @example
+ * // Basic usage in list view
+ *
+ *
+ * @example
+ * // Grid view with preview handler
+ * openPreviewModal(file)}
+ * onDelete={() => refetchFiles()}
+ * />
+ */
export function FileItem({ file, view = 'list', onDelete, onPreview }: FileItemProps) {
const [showMenu, setShowMenu] = useState(false);
const [downloading, setDownloading] = useState(false);
diff --git a/apps/frontend/src/components/storage/FileList.tsx b/apps/frontend/src/components/storage/FileList.tsx
index 9d9bee2f..c150f8fd 100644
--- a/apps/frontend/src/components/storage/FileList.tsx
+++ b/apps/frontend/src/components/storage/FileList.tsx
@@ -4,12 +4,41 @@ import { useFiles } from '@/hooks/useStorage';
import { StorageFile } from '@/services/api';
import { FileItem } from './FileItem';
+/**
+ * Props for the FileList component.
+ */
interface FileListProps {
+ /** Optional folder path to filter files */
folder?: string;
+ /** Callback fired when user requests file preview */
onPreview?: (file: StorageFile) => void;
+ /** Additional CSS classes to apply to the container */
className?: string;
}
+/**
+ * Displays a paginated, searchable list of files with grid/list view toggle.
+ * Fetches files from the storage API and provides search, pagination,
+ * and view mode switching. Handles loading, empty, and error states.
+ *
+ * @description Renders a file browser with search, pagination, and view modes.
+ * @param props - The component props
+ * @param props.folder - Optional folder to filter files by
+ * @param props.onPreview - Optional callback for file preview requests
+ * @param props.className - Additional CSS classes for the container
+ *
+ * @example
+ * // Basic usage
+ *
+ *
+ * @example
+ * // With folder filter and preview handler
+ * setPreviewFile(file)}
+ * className="mt-4"
+ * />
+ */
export function FileList({ folder, onPreview, className = '' }: FileListProps) {
const [view, setView] = useState<'grid' | 'list'>('list');
const [page, setPage] = useState(1);
diff --git a/apps/frontend/src/components/storage/FileUpload.tsx b/apps/frontend/src/components/storage/FileUpload.tsx
index 3f2e66e2..eba6c2d6 100644
--- a/apps/frontend/src/components/storage/FileUpload.tsx
+++ b/apps/frontend/src/components/storage/FileUpload.tsx
@@ -2,13 +2,23 @@ import { useState, useRef, useCallback } from 'react';
import { Upload, X, File, Image, FileText, Table, AlertCircle } from 'lucide-react';
import { useUploadFile } from '@/hooks/useStorage';
+/**
+ * Props for the FileUpload component.
+ */
interface FileUploadProps {
+ /** Target folder for uploaded files (default: 'files') */
folder?: string;
+ /** File visibility level: 'private', 'tenant', or 'public' (default: 'private') */
visibility?: 'private' | 'tenant' | 'public';
+ /** MIME types to accept (defaults to ALLOWED_TYPES) */
accept?: string;
- maxSize?: number; // in bytes
+ /** Maximum file size in bytes (default: 50MB) */
+ maxSize?: number;
+ /** Callback fired after successful upload with file id and filename */
onSuccess?: (file: { id: string; filename: string }) => void;
+ /** Callback fired when upload fails with the error */
onError?: (error: Error) => void;
+ /** Additional CSS classes to apply to the container */
className?: string;
}
@@ -42,6 +52,37 @@ function formatBytes(bytes: number): string {
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
}
+/**
+ * Drag-and-drop file upload component with progress indicator.
+ * Supports file validation (type and size), visual drag feedback,
+ * upload progress display, and error handling. Files can be selected
+ * via drag-and-drop or click-to-browse.
+ *
+ * @description Renders a drag-and-drop zone for uploading files with progress.
+ * @param props - The component props
+ * @param props.folder - Target folder for uploads (default: 'files')
+ * @param props.visibility - File visibility: 'private', 'tenant', or 'public'
+ * @param props.accept - MIME types to accept
+ * @param props.maxSize - Maximum file size in bytes (default: 50MB)
+ * @param props.onSuccess - Callback after successful upload
+ * @param props.onError - Callback on upload error
+ * @param props.className - Additional CSS classes
+ *
+ * @example
+ * // Basic usage
+ * console.log('Uploaded:', file.id)} />
+ *
+ * @example
+ * // With custom settings
+ * toast.error(err.message)}
+ * />
+ */
export function FileUpload({
folder = 'files',
visibility = 'private',
diff --git a/apps/frontend/src/components/storage/StorageUsageCard.tsx b/apps/frontend/src/components/storage/StorageUsageCard.tsx
index 1fa330d7..7cb3efc9 100644
--- a/apps/frontend/src/components/storage/StorageUsageCard.tsx
+++ b/apps/frontend/src/components/storage/StorageUsageCard.tsx
@@ -1,7 +1,11 @@
import { HardDrive, Folder } from 'lucide-react';
import { useStorageUsage } from '@/hooks/useStorage';
+/**
+ * Props for the StorageUsageCard component.
+ */
interface StorageUsageCardProps {
+ /** Additional CSS classes to apply to the card container */
className?: string;
}
@@ -12,6 +16,24 @@ function formatBytes(bytes: number): string {
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
}
+/**
+ * Displays storage usage statistics in a card format.
+ * Shows total bytes used, usage percentage with color-coded progress bar,
+ * file count, max file size, and breakdown by folder. Handles loading
+ * and error states gracefully.
+ *
+ * @description Renders a card showing storage quota usage and file statistics.
+ * @param props - The component props
+ * @param props.className - Additional CSS classes for the card container
+ *
+ * @example
+ * // Basic usage
+ *
+ *
+ * @example
+ * // With custom styling
+ *
+ */
export function StorageUsageCard({ className = '' }: StorageUsageCardProps) {
const { data, isLoading, error } = useStorageUsage();
diff --git a/apps/frontend/src/components/webhooks/WebhookCard.tsx b/apps/frontend/src/components/webhooks/WebhookCard.tsx
index 266e83bd..a5d01806 100644
--- a/apps/frontend/src/components/webhooks/WebhookCard.tsx
+++ b/apps/frontend/src/components/webhooks/WebhookCard.tsx
@@ -14,15 +14,50 @@ import {
} from 'lucide-react';
import clsx from 'clsx';
+/**
+ * Props for the WebhookCard component.
+ */
interface WebhookCardProps {
+ /** The webhook data to display */
webhook: Webhook;
+ /** Callback invoked when the user clicks the edit action */
onEdit: (webhook: Webhook) => void;
+ /** Callback invoked when the user clicks the delete action */
onDelete: (webhook: Webhook) => void;
+ /** Callback invoked when the user clicks the test/send action */
onTest: (webhook: Webhook) => void;
+ /** Callback invoked when the user toggles the webhook active state */
onToggle: (webhook: Webhook) => void;
+ /** Callback invoked when the user wants to view delivery history */
onViewDeliveries: (webhook: Webhook) => void;
}
+/**
+ * Displays a single webhook configuration as a card with status, events, and statistics.
+ *
+ * @description Renders a card showing webhook details including name, URL, subscribed events,
+ * delivery statistics, and a dropdown menu with actions (edit, test, view deliveries, toggle, delete).
+ *
+ * @param props - The component props
+ * @param props.webhook - The webhook data to display
+ * @param props.onEdit - Callback when user clicks edit
+ * @param props.onDelete - Callback when user clicks delete
+ * @param props.onTest - Callback when user clicks send test
+ * @param props.onToggle - Callback when user toggles active state
+ * @param props.onViewDeliveries - Callback when user clicks view deliveries
+ *
+ * @example
+ * ```tsx
+ * openEditModal(wh)}
+ * onDelete={(wh) => confirmDelete(wh)}
+ * onTest={(wh) => sendTestWebhook(wh)}
+ * onToggle={(wh) => toggleWebhookStatus(wh)}
+ * onViewDeliveries={(wh) => showDeliveryHistory(wh)}
+ * />
+ * ```
+ */
export function WebhookCard({
webhook,
onEdit,
diff --git a/apps/frontend/src/components/webhooks/WebhookDeliveryList.tsx b/apps/frontend/src/components/webhooks/WebhookDeliveryList.tsx
index ac015c7d..1124a1f3 100644
--- a/apps/frontend/src/components/webhooks/WebhookDeliveryList.tsx
+++ b/apps/frontend/src/components/webhooks/WebhookDeliveryList.tsx
@@ -11,11 +11,19 @@ import {
} from 'lucide-react';
import clsx from 'clsx';
+/**
+ * Props for the WebhookDeliveryList component.
+ */
interface WebhookDeliveryListProps {
+ /** Array of webhook delivery records to display */
deliveries: WebhookDelivery[];
+ /** Whether the list is currently loading data */
isLoading?: boolean;
+ /** Callback invoked when the user requests to retry a failed delivery */
onRetry: (deliveryId: string) => void;
+ /** Callback invoked when the user requests to load more deliveries (pagination) */
onLoadMore?: () => void;
+ /** Indicates whether there are more deliveries available to load */
hasMore?: boolean;
}
@@ -45,6 +53,16 @@ const statusConfig: Record<
},
};
+/**
+ * Renders a single delivery record as an expandable row.
+ *
+ * @description Displays delivery summary (event type, timestamp, status) with expand/collapse
+ * functionality to show detailed information including payload, response, and retry options.
+ *
+ * @param props - The component props
+ * @param props.delivery - The webhook delivery record to display
+ * @param props.onRetry - Callback when user clicks retry on a failed delivery
+ */
function DeliveryRow({
delivery,
onRetry,
@@ -183,6 +201,31 @@ function DeliveryRow({
);
}
+/**
+ * Displays a paginated list of webhook delivery attempts with their status and details.
+ *
+ * @description Renders a list of delivery records showing status (delivered, failed, pending, retrying),
+ * event type, timestamps, payload data, and response information. Supports pagination via "Load More"
+ * and allows retrying failed deliveries.
+ *
+ * @param props - The component props
+ * @param props.deliveries - Array of webhook delivery records to display
+ * @param props.isLoading - Whether data is currently being loaded
+ * @param props.onRetry - Callback when user requests to retry a failed delivery
+ * @param props.onLoadMore - Optional callback to load more deliveries (pagination)
+ * @param props.hasMore - Whether there are more deliveries available to load
+ *
+ * @example
+ * ```tsx
+ * retryDelivery(deliveryId)}
+ * onLoadMore={() => fetchMoreDeliveries()}
+ * hasMore={hasMoreDeliveries}
+ * />
+ * ```
+ */
export function WebhookDeliveryList({
deliveries,
isLoading,
diff --git a/apps/frontend/src/components/webhooks/WebhookForm.tsx b/apps/frontend/src/components/webhooks/WebhookForm.tsx
index ef8f199e..4932938a 100644
--- a/apps/frontend/src/components/webhooks/WebhookForm.tsx
+++ b/apps/frontend/src/components/webhooks/WebhookForm.tsx
@@ -3,14 +3,58 @@ import { Webhook, CreateWebhookRequest, UpdateWebhookRequest, WebhookEvent } fro
import { X, Plus, Trash2, Eye, EyeOff, Copy, Check } from 'lucide-react';
import clsx from 'clsx';
+/**
+ * Props for the WebhookForm component.
+ */
interface WebhookFormProps {
+ /** Existing webhook data for editing, or null/undefined for creating a new webhook */
webhook?: Webhook | null;
+ /** List of available webhook events that can be subscribed to */
events: WebhookEvent[];
+ /** Callback invoked when the form is submitted with valid data */
onSubmit: (data: CreateWebhookRequest | UpdateWebhookRequest) => void;
+ /** Callback invoked when the user cancels the form */
onCancel: () => void;
+ /** Whether the form submission is in progress */
isLoading?: boolean;
}
+/**
+ * Form component for creating or editing webhook configurations.
+ *
+ * @description Provides a comprehensive form for webhook management including:
+ * - Name and description fields
+ * - HTTPS endpoint URL with validation
+ * - Event selection checkboxes
+ * - Custom HTTP headers management
+ * - Signing secret display (edit mode only)
+ *
+ * @param props - The component props
+ * @param props.webhook - Existing webhook data for editing, or null for creating
+ * @param props.events - List of available webhook events to subscribe to
+ * @param props.onSubmit - Callback when form is submitted with valid data
+ * @param props.onCancel - Callback when user cancels the form
+ * @param props.isLoading - Whether submission is in progress (disables form)
+ *
+ * @example
+ * ```tsx
+ * // Creating a new webhook
+ * createWebhook(data)}
+ * onCancel={() => closeModal()}
+ * />
+ *
+ * // Editing an existing webhook
+ * updateWebhook(existingWebhook.id, data)}
+ * onCancel={() => closeModal()}
+ * isLoading={isSaving}
+ * />
+ * ```
+ */
export function WebhookForm({
webhook,
events,
diff --git a/apps/frontend/src/components/whatsapp/WhatsAppTestMessage.tsx b/apps/frontend/src/components/whatsapp/WhatsAppTestMessage.tsx
index 239caa26..f5a8d10c 100644
--- a/apps/frontend/src/components/whatsapp/WhatsAppTestMessage.tsx
+++ b/apps/frontend/src/components/whatsapp/WhatsAppTestMessage.tsx
@@ -1,10 +1,46 @@
import React, { useState } from 'react';
import { useTestWhatsAppConnection } from '../../hooks/useWhatsApp';
+/**
+ * Props for the WhatsAppTestMessage component.
+ */
interface WhatsAppTestMessageProps {
+ /**
+ * When true, disables the input field and submit button.
+ * Useful when the WhatsApp integration is not configured.
+ * @default false
+ */
disabled?: boolean;
}
+/**
+ * A form component for testing WhatsApp Business API connectivity.
+ *
+ * Allows users to send a test message to a specified phone number in E.164 format
+ * to verify that the WhatsApp integration is working correctly.
+ *
+ * @description Renders a card with a phone number input and submit button.
+ * Uses the useTestWhatsAppConnection hook to send the test message.
+ * Shows loading state while the message is being sent.
+ *
+ * @param props - The component props
+ * @param props.disabled - Optional flag to disable the form controls
+ *
+ * @example
+ * // Basic usage
+ *
+ *
+ * @example
+ * // Disabled state when integration is not configured
+ *
+ *
+ * @example
+ * // Usage within a settings panel
+ *