From 4d66eacab2e9fd16462410d152f5ecb12dabcb93 Mon Sep 17 00:00:00 2001 From: Igor Loskutov Date: Tue, 16 Sep 2025 17:15:13 -0400 Subject: [PATCH] calendar refresh quick action icon --- .../(app)/rooms/_components/ICSSettings.tsx | 36 ++++++---- www/app/(app)/rooms/_components/RoomTable.tsx | 72 ++++++++++++++++++- 2 files changed, 94 insertions(+), 14 deletions(-) diff --git a/www/app/(app)/rooms/_components/ICSSettings.tsx b/www/app/(app)/rooms/_components/ICSSettings.tsx index a39780d2..beb4d9fa 100644 --- a/www/app/(app)/rooms/_components/ICSSettings.tsx +++ b/www/app/(app)/rooms/_components/ICSSettings.tsx @@ -201,20 +201,32 @@ export default function ICSSettings({ bg="gray.100" _hover={{ bg: "gray.200" }} _focus={{ bg: "gray.200" }} - pr="48px" + pr="90px" width="100%" /> - - {justCopied ? : } - + + + {syncStatus === "syncing" ? ( + + ) : ( + + )} + + + {justCopied ? : } + + diff --git a/www/app/(app)/rooms/_components/RoomTable.tsx b/www/app/(app)/rooms/_components/RoomTable.tsx index 8b5e1ae1..9ad64880 100644 --- a/www/app/(app)/rooms/_components/RoomTable.tsx +++ b/www/app/(app)/rooms/_components/RoomTable.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import { Box, Table, @@ -9,12 +9,15 @@ import { Spinner, Badge, VStack, + Icon, } from "@chakra-ui/react"; -import { LuLink } from "react-icons/lu"; +import { LuLink, LuRefreshCw } from "react-icons/lu"; +import { FaCalendarAlt } from "react-icons/fa"; import type { components } from "../../../reflector-api"; import { useRoomActiveMeetings, useRoomUpcomingMeetings, + useRoomIcsSync, } from "../../../lib/apiHooks"; type Room = components["schemas"]["Room"]; @@ -23,6 +26,34 @@ type CalendarEventResponse = components["schemas"]["CalendarEventResponse"]; import { RoomActionsMenu } from "./RoomActionsMenu"; import { MEETING_DEFAULT_TIME_MINUTES } from "../../../[roomName]/[meetingId]/constants"; +// Custom icon component that combines calendar and refresh icons +const CalendarSyncIcon = () => ( + + + + + + +); + interface RoomTableProps { rooms: Room[]; linkCopied: string; @@ -148,6 +179,28 @@ export function RoomTable({ onDelete, loading, }: RoomTableProps) { + const [syncingRooms, setSyncingRooms] = useState>(new Set()); + const syncMutation = useRoomIcsSync(); + + const handleForceSync = async (roomName: string) => { + setSyncingRooms((prev) => new Set(prev).add(roomName)); + try { + await syncMutation.mutateAsync({ + params: { + path: { room_name: roomName }, + }, + }); + } catch (err) { + console.error("Failed to sync calendar:", err); + } finally { + setSyncingRooms((prev) => { + const next = new Set(prev); + next.delete(roomName); + return next; + }); + } + }; + return ( {loading && ( @@ -217,6 +270,21 @@ export function RoomTable({ + {room.ics_enabled && ( + handleForceSync(room.name)} + size="sm" + variant="ghost" + disabled={syncingRooms.has(room.name)} + > + {syncingRooms.has(room.name) ? ( + + ) : ( + + )} + + )} {linkCopied === room.name ? ( Copied!