Types: CalendarPermission, SharedCalendarMembership, CalendarMemberInfo, CalendarInvite, EventLockInfo. Calendar type extended with is_shared. Hooks: useCalendars extended with shared calendar polling (5s). useSharedCalendars for member CRUD, invite responses, color updates. useConnections cascade invalidation on disconnect. New components: PermissionBadge, CalendarMemberSearch, CalendarMemberRow, CalendarMemberList, SharedCalendarSection, SharedCalendarSettings (non-owner dialog with color, members, leave). Modified: CalendarForm (sharing toggle, member management for owners), CalendarSidebar (shared calendars section with localStorage visibility), CalendarPage (shared calendar ID integration in event filtering), NotificationToaster (calendar_invite toast with accept/decline), NotificationsPage (calendar_invite inline actions + type icons). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
25 lines
980 B
TypeScript
25 lines
980 B
TypeScript
import { Eye, Pencil, Shield } from 'lucide-react';
|
|
import type { CalendarPermission } from '@/types';
|
|
|
|
const config: Record<CalendarPermission, { label: string; icon: typeof Eye; bg: string; text: string }> = {
|
|
read_only: { label: 'Read Only', icon: Eye, bg: 'bg-blue-500/10', text: 'text-blue-400' },
|
|
create_modify: { label: 'Create/Modify', icon: Pencil, bg: 'bg-amber-500/10', text: 'text-amber-400' },
|
|
full_access: { label: 'Full Access', icon: Shield, bg: 'bg-green-500/10', text: 'text-green-400' },
|
|
};
|
|
|
|
interface PermissionBadgeProps {
|
|
permission: CalendarPermission;
|
|
showIcon?: boolean;
|
|
}
|
|
|
|
export default function PermissionBadge({ permission, showIcon = true }: PermissionBadgeProps) {
|
|
const c = config[permission];
|
|
const Icon = c.icon;
|
|
return (
|
|
<span className={`inline-flex items-center gap-1 text-[9px] px-1.5 py-0.5 rounded-full font-medium ${c.bg} ${c.text}`}>
|
|
{showIcon && <Icon className="h-3 w-3" />}
|
|
{c.label}
|
|
</span>
|
|
);
|
|
}
|