diff --git a/apps/desktop2/public/assets/dynamic.gif b/apps/desktop2/public/assets/dynamic.gif new file mode 100644 index 000000000..9547b1074 Binary files /dev/null and b/apps/desktop2/public/assets/dynamic.gif differ diff --git a/apps/desktop2/src/components/floating-chat-button.tsx b/apps/desktop2/src/components/floating-chat-button.tsx new file mode 100644 index 000000000..f80f2d04e --- /dev/null +++ b/apps/desktop2/src/components/floating-chat-button.tsx @@ -0,0 +1,72 @@ +import { Popover, PopoverContent, PopoverTrigger } from "@hypr/ui/components/ui/popover"; +import { cn } from "@hypr/ui/lib/utils"; +import { useState } from "react"; + +export function FloatingChatButton() { + const [isOpen, setIsOpen] = useState(false); + + return ( + + + + + + +
+
+

Chat Assistant

+ +
+ +
+
+ Chat interface will appear here +
+
+ +
+ +
+
+
+
+ ); +} diff --git a/apps/desktop2/src/components/main/main-area.tsx b/apps/desktop2/src/components/main/main-area.tsx index f7c6ea439..05f59b6be 100644 --- a/apps/desktop2/src/components/main/main-area.tsx +++ b/apps/desktop2/src/components/main/main-area.tsx @@ -1,11 +1,10 @@ import { useRouteContext } from "@tanstack/react-router"; import { clsx } from "clsx"; -import { addMonths, eachDayOfInterval, endOfMonth, format, getDay, startOfMonth } from "date-fns"; +import { addMonths, eachDayOfInterval, endOfMonth, format, getDay, isSameMonth, startOfMonth } from "date-fns"; import { CalendarIcon, - ChevronLeftIcon, - ChevronRightIcon, CogIcon, + FileTextIcon, FolderIcon, PanelLeftOpenIcon, PencilIcon, @@ -16,10 +15,10 @@ import { useCallback } from "react"; import { commands as windowsCommands } from "@hypr/plugin-windows"; import NoteEditor from "@hypr/tiptap/editor"; -import { ChatPanelButton } from "@hypr/ui/components/block/chat-panel-button"; +import { CalendarStructure } from "@hypr/ui/components/block/calendar-structure"; +import { TabHeader } from "@hypr/ui/components/block/tab-header"; import TitleInput from "@hypr/ui/components/block/title-input"; -import { Button } from "@hypr/ui/components/ui/button"; -import { useLeftSidebar, useRightPanel } from "@hypr/utils/contexts"; +import { useLeftSidebar } from "@hypr/utils/contexts"; import * as persisted from "../../store/tinybase/persisted"; import { useTabs } from "../../store/zustand/tabs"; import { rowIdfromTab, type Tab, uniqueIdfromTab } from "../../store/zustand/tabs"; @@ -41,7 +40,6 @@ export function MainContent() { export function MainHeader() { const { persistedStore, internalStore } = useRouteContext({ from: "__root__" }); - const { isExpanded: isRightPanelExpanded, togglePanel: toggleRightPanel } = useRightPanel(); const { isExpanded: isLeftPanelExpanded, togglePanel: toggleLeftPanel } = useLeftSidebar(); const { openNew } = useTabs(); @@ -104,11 +102,6 @@ export function MainHeader() { className="cursor-pointer h-5 w-5 text-muted-foreground hover:text-foreground" /> - - ); } @@ -341,6 +334,15 @@ function TabContentNote({ tab }: { tab: Tab }) { value={sessionRow.title ?? ""} onChange={(e) => handleEditTitle(e.target.value)} /> + {}} + currentTab="raw" + onTabChange={() => {}} + isCurrentlyRecording={false} + shouldShowTab={true} + shouldShowEnhancedTab={false} + /> handleEditRawMd(e)} @@ -427,7 +429,7 @@ function TabContentCalendar({ tab }: { tab: Tab }) { const monthStart = startOfMonth(tab.month); const monthEnd = endOfMonth(tab.month); const days = eachDayOfInterval({ start: monthStart, end: monthEnd }).map((day) => format(day, "yyyy-MM-dd")); - const startDayOfWeek = getDay(monthStart); // 0 = Sunday, 6 = Saturday + const startDayOfWeek = getDay(monthStart); const weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; const handlePreviousMonth = () => { @@ -443,85 +445,103 @@ function TabContentCalendar({ tab }: { tab: Tab }) { }; return ( -
-
-
- {format(tab.month, "MMMM yyyy")} -
-
- - - - - -
-
-
- {weekDays.map((day) => ( -
- {day} -
- ))} - {Array.from({ length: startDayOfWeek }).map((_, i) =>
)} - {days.map((day) => )} -
-
+ + {days.map((day) => ( + + ))} + ); } -function TabContentCalendarDay({ day }: { day: string }) { +function TabContentCalendarDay({ day, isCurrentMonth }: { day: string; isCurrentMonth: boolean }) { const eventIds = persisted.UI.useSliceRowIds( persisted.INDEXES.eventsByDate, day, persisted.STORE_ID, ); + const sessionIds = persisted.UI.useSliceRowIds( + persisted.INDEXES.sessionByDateWithoutEvent, + day, + persisted.STORE_ID, + ); + const dayNumber = format(new Date(day), "d"); const isToday = format(new Date(), "yyyy-MM-dd") === day; + const dayOfWeek = getDay(new Date(day)); + const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; return (
-
- {dayNumber} +
+
+
+ + {dayNumber} + +
+
+
+ +
+
+ {eventIds.map((eventId) => )} + {sessionIds.map((sessionId) => )} +
-
- {eventIds?.map((rowId) => )} +
+ ); +} + +function TabContentCalendarDayEvents({ eventId }: { eventId: string }) { + const event = persisted.UI.useRow("events", eventId, persisted.STORE_ID); + + return ( +
+ +
+ {event.title}
); } -function TabContentCalendarDayEvent({ rowId }: { rowId: string }) { - const event = persisted.UI.useRow("events", rowId, persisted.STORE_ID); - return
{event.title}
; +function TabContentCalendarDaySessions({ sessionId }: { sessionId: string }) { + const session = persisted.UI.useRow("sessions", sessionId, persisted.STORE_ID); + return ( +
+ +
+ {session.title} +
+
+ ); } function TabContentFolder({ tab }: { tab: Tab }) { diff --git a/apps/desktop2/src/routes/app/main/_layout.index.tsx b/apps/desktop2/src/routes/app/main/_layout.index.tsx index 9ac5067f8..cb026cfb3 100644 --- a/apps/desktop2/src/routes/app/main/_layout.index.tsx +++ b/apps/desktop2/src/routes/app/main/_layout.index.tsx @@ -1,8 +1,8 @@ import { createFileRoute } from "@tanstack/react-router"; import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@hypr/ui/components/ui/resizable"; -import { useLeftSidebar, useRightPanel } from "@hypr/utils/contexts"; -import { Chat } from "../../../components/chat"; +import { useLeftSidebar } from "@hypr/utils/contexts"; +import { FloatingChatButton } from "../../../components/floating-chat-button"; import { LeftSidebar } from "../../../components/main/left-sidebar"; import { MainContent, MainHeader } from "../../../components/main/main-area"; @@ -11,7 +11,6 @@ export const Route = createFileRoute("/app/main/_layout/")({ }); function Component() { - const { isExpanded: isRightPanelExpanded } = useRightPanel(); const { isExpanded: isLeftPanelExpanded } = useLeftSidebar(); return ( @@ -27,21 +26,10 @@ function Component() {
- {isRightPanelExpanded - ? ( - - - - - - - - - - ) - : } +
+ ); } diff --git a/apps/desktop2/src/store/tinybase/persisted.ts b/apps/desktop2/src/store/tinybase/persisted.ts index e762fb30b..255d56d6c 100644 --- a/apps/desktop2/src/store/tinybase/persisted.ts +++ b/apps/desktop2/src/store/tinybase/persisted.ts @@ -371,6 +371,21 @@ export const StoreComponent = () => { (a, b) => a.localeCompare(b), (a, b) => String(a).localeCompare(String(b)), ) + .setIndexDefinition( + INDEXES.sessionByDateWithoutEvent, + "sessions", + (getCell) => { + if (getCell("event_id")) { + return ""; + } + + const d = new Date(getCell("created_at")!); + return format(d, "yyyy-MM-dd"); + }, + "created_at", + (a, b) => a.localeCompare(b), + (a, b) => String(a).localeCompare(String(b)), + ) .setIndexDefinition(INDEXES.tagsByName, "tags", "name") .setIndexDefinition(INDEXES.tagSessionsBySession, "mapping_tag_session", "session_id") .setIndexDefinition(INDEXES.tagSessionsByTag, "mapping_tag_session", "tag_id") @@ -412,6 +427,7 @@ export const INDEXES = { sessionsByFolder: "sessionsByFolder", eventsByCalendar: "eventsByCalendar", eventsByDate: "eventsByDate", + sessionByDateWithoutEvent: "sessionByDateWithoutEvent", tagsByName: "tagsByName", tagSessionsBySession: "tagSessionsBySession", tagSessionsByTag: "tagSessionsByTag", diff --git a/packages/ui/src/components/block/calendar-structure.tsx b/packages/ui/src/components/block/calendar-structure.tsx new file mode 100644 index 000000000..7db80fc81 --- /dev/null +++ b/packages/ui/src/components/block/calendar-structure.tsx @@ -0,0 +1,71 @@ +import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; +import { Button } from "../ui/button"; + +interface CalendarStructureProps { + monthLabel: string; + weekDays: string[]; + startDayOfWeek: number; + onPreviousMonth: () => void; + onNextMonth: () => void; + onToday: () => void; + children: React.ReactNode; +} + +export const CalendarStructure = ({ + monthLabel, + weekDays, + startDayOfWeek, + onPreviousMonth, + onNextMonth, + onToday, + children, +}: CalendarStructureProps) => { + return ( +
+
+
{monthLabel}
+
+ + + + + +
+
+
+ {weekDays.map((day) => ( +
+ {day} +
+ ))} +
+
+ {Array.from({ length: startDayOfWeek }).map((_, i) => ( +
+ ))} + {children} +
+
+ ); +};