From d85f54e1673c89d90595b3a0fab4eaa44d8c2976 Mon Sep 17 00:00:00 2001 From: John Jeong Date: Tue, 17 Dec 2024 09:34:12 +0900 Subject: [PATCH 1/6] changed icons to remix from lucide + changed note controls icon styles --- apps/desktop/package.json | 2 +- .../src/components/home/NewUserBanner.tsx | 4 +-- .../src/components/home/UpcomingEvents.tsx | 6 ++-- .../src/components/layout/ExportMenu.tsx | 15 ++++++--- apps/desktop/src/components/layout/NavBar.tsx | 12 ++++--- .../components/layout/NavigationButtons.tsx | 6 ++-- .../modals/settings/SettingsTabs.tsx | 32 +++++++++---------- .../modals/settings/tabs/Integrations.tsx | 15 +++++---- .../modals/settings/tabs/Profile.tsx | 4 +-- .../src/components/note/NoteControl.tsx | 10 +++--- .../src/components/note/NoteHeader.tsx | 4 +-- apps/desktop/src/types/db.ts | 19 +++-------- pnpm-lock.yaml | 19 ++++------- 13 files changed, 71 insertions(+), 77 deletions(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 66543c8371..a757816b30 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -21,6 +21,7 @@ "@radix-ui/react-select": "^2.1.3", "@radix-ui/react-switch": "^1.1.2", "@radix-ui/react-tabs": "^1.1.2", + "@remixicon/react": "^4.5.0", "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "^2.2.0", "@tauri-apps/plugin-fs": "^2.0.3", @@ -36,7 +37,6 @@ "date-fns": "^4.1.0", "embla-carousel": "^8.5.1", "embla-carousel-react": "^8.5.1", - "lucide-react": "^0.468.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-resizable-panels": "^2.1.7", diff --git a/apps/desktop/src/components/home/NewUserBanner.tsx b/apps/desktop/src/components/home/NewUserBanner.tsx index e48b0a0e3c..fba1c67f59 100644 --- a/apps/desktop/src/components/home/NewUserBanner.tsx +++ b/apps/desktop/src/components/home/NewUserBanner.tsx @@ -1,4 +1,4 @@ -import { ArrowRight } from "lucide-react"; +import { RiArrowRightLine } from "@remixicon/react"; interface NewUserBannerProps { onDemoClick: () => void; @@ -14,7 +14,7 @@ export const NewUserBanner = ({ onDemoClick }: NewUserBannerProps) => { className="flex items-center gap-2 rounded-full bg-white px-4 py-2 text-blue-600 transition-colors hover:bg-blue-50" > 데모 체험 - + diff --git a/apps/desktop/src/components/home/UpcomingEvents.tsx b/apps/desktop/src/components/home/UpcomingEvents.tsx index 7b62c7e962..e90a985829 100644 --- a/apps/desktop/src/components/home/UpcomingEvents.tsx +++ b/apps/desktop/src/components/home/UpcomingEvents.tsx @@ -1,7 +1,7 @@ import useEmblaCarousel from "embla-carousel-react"; import { Note } from "../../types"; import { EventCard } from "./EventCard"; -import { ChevronLeft, ChevronRight } from "lucide-react"; +import { RiArrowLeftSLine, RiArrowRightSLine } from "@remixicon/react"; import { useCallback } from "react"; interface UpcomingEventsProps { @@ -50,13 +50,13 @@ export const UpcomingEvents = ({ onClick={scrollPrev} className="absolute -left-4 top-1/2 -translate-y-1/2 rounded-full bg-white p-2 shadow-lg hover:bg-gray-50" > - + )} diff --git a/apps/desktop/src/components/layout/ExportMenu.tsx b/apps/desktop/src/components/layout/ExportMenu.tsx index 0db6ac5593..86467c818e 100644 --- a/apps/desktop/src/components/layout/ExportMenu.tsx +++ b/apps/desktop/src/components/layout/ExportMenu.tsx @@ -1,5 +1,10 @@ import { useRef, useState } from "react"; -import { Share, Copy, File, FileText } from "lucide-react"; +import { + RiShareLine, + RiFileCopyLine, + RiFileTextLine, + RiFileTextFill, +} from "@remixicon/react"; import { useClickOutside } from "../../hooks/useClickOutside"; @@ -20,7 +25,7 @@ export default function ExportMenu() { className="rounded-md p-2 text-gray-700 hover:bg-gray-100" aria-label={isOpen ? "Close export menu" : "Open export menu"} > - + {isOpen && (
@@ -32,7 +37,7 @@ export default function ExportMenu() { }} className="flex w-full items-center gap-2 px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100" > - + 클립보드에 복사
diff --git a/apps/desktop/src/components/layout/NavBar.tsx b/apps/desktop/src/components/layout/NavBar.tsx index e81c053491..a40b42efba 100644 --- a/apps/desktop/src/components/layout/NavBar.tsx +++ b/apps/desktop/src/components/layout/NavBar.tsx @@ -1,6 +1,10 @@ import { useCallback } from "react"; import { useNavigate, useLocation } from "react-router"; -import { PanelRightClose, PanelRightOpen, Menu } from "lucide-react"; +import { + RiMenuLine, + RiSidebarUnfoldLine, + RiSidebarFoldLine, +} from "@remixicon/react"; import SearchModal from "../modals/search/SearchModal"; import SettingsModal from "../modals/settings/SettingsModal"; @@ -51,7 +55,7 @@ export default function NavBar() { onClick={handleSettingsClick} className="flex items-center rounded p-2 hover:bg-gray-100" > - + )} @@ -70,9 +74,9 @@ export default function NavBar() { aria-label={isPanelOpen ? "Close panel" : "Open panel"} > {isPanelOpen ? ( - + ) : ( - + )} ) : ( diff --git a/apps/desktop/src/components/layout/NavigationButtons.tsx b/apps/desktop/src/components/layout/NavigationButtons.tsx index 298655725c..e5c251f807 100644 --- a/apps/desktop/src/components/layout/NavigationButtons.tsx +++ b/apps/desktop/src/components/layout/NavigationButtons.tsx @@ -1,4 +1,4 @@ -import { Home, ChevronLeft } from "lucide-react"; +import { RiHome2Line, RiArrowLeftSLine } from "@remixicon/react"; interface NavigationButtonsProps { onHomeClick: () => void; @@ -12,10 +12,10 @@ export default function NavigationButtons({ return ( <> ); diff --git a/apps/desktop/src/components/modals/settings/SettingsTabs.tsx b/apps/desktop/src/components/modals/settings/SettingsTabs.tsx index 69995ee0c7..61a8cfbd81 100644 --- a/apps/desktop/src/components/modals/settings/SettingsTabs.tsx +++ b/apps/desktop/src/components/modals/settings/SettingsTabs.tsx @@ -1,13 +1,13 @@ import * as Tabs from "@radix-ui/react-tabs"; import { - Settings, - MessageSquare, - CreditCard, - Calendar, - Bell, - UserCircle, - Cable, -} from "lucide-react"; + RiSettings4Line, + RiMessage2Line, + RiBankCardLine, + RiCalendarLine, + RiNotification3Line, + RiUser3Line, + RiPlugLine, +} from "@remixicon/react"; interface TabItem { value: string; @@ -17,13 +17,13 @@ interface TabItem { export function SettingsTabs() { const mainTabs: TabItem[] = [ - { value: "profile", label: "프로필", icon: UserCircle }, - { value: "general", label: "일반", icon: Settings }, - { value: "feedback", label: "피드백", icon: MessageSquare }, - { value: "billing", label: "결제", icon: CreditCard }, - { value: "calendar", label: "캘린더", icon: Calendar }, - { value: "notification", label: "알림", icon: Bell }, - { value: "integrations", label: "연동", icon: Cable }, + { value: "profile", label: "프로필", icon: RiUser3Line }, + { value: "general", label: "일반", icon: RiSettings4Line }, + { value: "feedback", label: "피드백", icon: RiMessage2Line }, + { value: "billing", label: "결제", icon: RiBankCardLine }, + { value: "calendar", label: "캘린더", icon: RiCalendarLine }, + { value: "notification", label: "알림", icon: RiNotification3Line }, + { value: "integrations", label: "연동", icon: RiPlugLine }, ]; const TabButton = ({ tab }: { tab: TabItem }) => ( @@ -32,7 +32,7 @@ export function SettingsTabs() { value={tab.value} className="flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 focus:outline-none data-[state=active]:bg-white data-[state=active]:text-blue-600" > - + {tab.label} ); diff --git a/apps/desktop/src/components/modals/settings/tabs/Integrations.tsx b/apps/desktop/src/components/modals/settings/tabs/Integrations.tsx index 77acfcfb62..2c04ecc6ec 100644 --- a/apps/desktop/src/components/modals/settings/tabs/Integrations.tsx +++ b/apps/desktop/src/components/modals/settings/tabs/Integrations.tsx @@ -1,6 +1,8 @@ -import SlackIcon from "../../../../constants/icons/SlackIcon"; -import NotionIcon from "../../../../constants/icons/NotionIcon"; -import { ExternalLink } from "lucide-react"; +import { + RiSlackFill, + RiNotionFill, + RiExternalLinkLine, +} from "@remixicon/react"; interface IntegrationCardProps { title: string; @@ -28,7 +30,7 @@ function IntegrationCard({ onClick={onClick} className="inline-flex items-center gap-2 rounded-md border border-transparent bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2" > - + 연결하기 @@ -40,7 +42,7 @@ export function Integrations() { { title: "Slack 연동하기", description: "Slack에서 미팅 알림을 받고 상태를 자동으로 업데이트하세요", - icon: , + icon: , onClick: () => { /* TODO: Implement Slack connection */ }, @@ -48,8 +50,7 @@ export function Integrations() { { title: "Notion 연동하기", description: "미팅 노트를 Notion에 자동으로 동기화하세요", - icon: , - + icon: , onClick: () => { /* TODO: Implement Notion connection */ }, diff --git a/apps/desktop/src/components/modals/settings/tabs/Profile.tsx b/apps/desktop/src/components/modals/settings/tabs/Profile.tsx index b80d2de788..d223bcf76f 100644 --- a/apps/desktop/src/components/modals/settings/tabs/Profile.tsx +++ b/apps/desktop/src/components/modals/settings/tabs/Profile.tsx @@ -1,5 +1,5 @@ import { useState, useRef } from "react"; -import { UserCircle } from "lucide-react"; +import { RiUser3Line } from "@remixicon/react"; export function Profile() { const [fullName, setFullName] = useState(""); @@ -46,7 +46,7 @@ export function Profile() { className="h-full w-full object-cover" /> ) : ( - + )} @@ -60,17 +60,17 @@ export default function NoteControl({ onClick={onPauseResume} className={`flex items-center gap-2 rounded-full px-4 py-1.5 text-sm ${ isPaused - ? "bg-gray-600 text-white hover:bg-gray-800" - : "animate-pulse bg-red-600 text-white hover:bg-red-800" + ? "border-2 border-gray-600 bg-gray-600 text-white hover:bg-gray-700" + : "border-2 border-red-600 bg-white text-red-600" }`} > -
+
{isPaused ? "일시정지 중" : formatTime(recordingTime)} ) : ( diff --git a/apps/desktop/src/components/note/NoteHeader.tsx b/apps/desktop/src/components/note/NoteHeader.tsx index 34502251c9..e1cffb01fd 100644 --- a/apps/desktop/src/components/note/NoteHeader.tsx +++ b/apps/desktop/src/components/note/NoteHeader.tsx @@ -1,4 +1,4 @@ -import { Calendar } from "lucide-react"; +import { RiCalendarLine } from "@remixicon/react"; import type { Note } from "../../types"; import { formatMeetingTime } from "../../utils/time"; import NoteControl from "./NoteControl"; @@ -42,7 +42,7 @@ export default function NoteHeader({
{note?.calendarEvent && (
- + {note.calendarEvent.summary}{" "} {formatMeetingTime(note.calendarEvent.start)} ~{" "} diff --git a/apps/desktop/src/types/db.ts b/apps/desktop/src/types/db.ts index 4fd2ab41f8..82483f8fc7 100644 --- a/apps/desktop/src/types/db.ts +++ b/apps/desktop/src/types/db.ts @@ -2,20 +2,9 @@ // This file has been generated by Specta. DO NOT EDIT. -export type Session = { - id: string; - start: string; - end: string | null; - tags: string[]; - raw_memo: string; - processed_memo: string; - raw_transcript: string; -}; +export type Session = { id: string; start: string; end: string | null; tags: string[]; raw_memo: string; processed_memo: string; raw_transcript: string } -export type Transcript = { speakers: string[]; blocks: TranscriptBlock[] }; +export type Transcript = { speakers: string[]; blocks: TranscriptBlock[] } + +export type TranscriptBlock = { timestamp: string; text: string; speaker: string } -export type TranscriptBlock = { - timestamp: string; - text: string; - speaker: string; -}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 708384eb5c..0bfdc58ddf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: '@radix-ui/react-tabs': specifier: ^1.1.2 version: 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@remixicon/react': + specifier: ^4.5.0 + version: 4.5.0(react@18.3.1) '@tauri-apps/api': specifier: ^2 version: 2.1.1 @@ -83,9 +86,6 @@ importers: embla-carousel-react: specifier: ^8.5.1 version: 8.5.1(react@18.3.1) - lucide-react: - specifier: ^0.468.0 - version: 0.468.0(react@18.3.1) react: specifier: ^18.2.0 version: 18.3.1 @@ -2675,11 +2675,6 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lucide-react@0.468.0: - resolution: {integrity: sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc - markdown-extensions@2.0.0: resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} engines: {node: '>=16'} @@ -4763,6 +4758,10 @@ snapshots: '@remirror/core-constants@3.0.0': {} + '@remixicon/react@4.5.0(react@18.3.1)': + dependencies: + react: 18.3.1 + '@remixicon/react@4.5.0(react@19.0.0)': dependencies: react: 19.0.0 @@ -6455,10 +6454,6 @@ snapshots: dependencies: yallist: 3.1.1 - lucide-react@0.468.0(react@18.3.1): - dependencies: - react: 18.3.1 - markdown-extensions@2.0.0: {} markdown-it@14.1.0: From 78616f10a8dafd41e073691437cbb5d5e7cb992a Mon Sep 17 00:00:00 2001 From: John Jeong Date: Tue, 17 Dec 2024 09:54:34 +0900 Subject: [PATCH 2/6] working on improving layout --- apps/desktop/package.json | 1 + apps/desktop/src/App.tsx | 4 +-- .../src/components/note/NoteEditor.tsx | 11 ++++++-- .../desktop/src/components/note/SidePanel.tsx | 26 ++++++++++++++++--- apps/desktop/src/mocks/data.ts | 10 ++++++- apps/desktop/src/pages/Home.tsx | 17 +++++------- apps/desktop/src/pages/Note.tsx | 16 +++++++++--- apps/web/src/components/layout/header.tsx | 22 +--------------- apps/web/src/components/ui/header-button.tsx | 6 ++--- pnpm-lock.yaml | 14 ++++++++++ 10 files changed, 81 insertions(+), 46 deletions(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index a757816b30..ddfc673a8a 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -28,6 +28,7 @@ "@tauri-apps/plugin-log": "^2.2.0", "@tauri-apps/plugin-updater": "^2.0.0", "@tiptap/extension-highlight": "^2.10.3", + "@tiptap/extension-placeholder": "^2.10.3", "@tiptap/extension-typography": "^2.10.3", "@tiptap/pm": "^2.10.3", "@tiptap/react": "^2.10.3", diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index 28d934c3f4..31aa4fd0eb 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -1,8 +1,6 @@ import { useEffect } from "react"; import { BrowserRouter, Routes, Route } from "react-router"; - import { UIProvider } from "./contexts/UIContext"; - import NavBar from "./components/layout/NavBar"; import Home from "./pages/Home"; import Note from "./pages/Note"; @@ -29,7 +27,7 @@ function App() {
-
+
} /> } /> diff --git a/apps/desktop/src/components/note/NoteEditor.tsx b/apps/desktop/src/components/note/NoteEditor.tsx index 597630fc6d..37850e035c 100644 --- a/apps/desktop/src/components/note/NoteEditor.tsx +++ b/apps/desktop/src/components/note/NoteEditor.tsx @@ -1,11 +1,11 @@ import "../../styles/editor.css"; import { useEffect } from "react"; - import { EditorContent, useEditor } from "@tiptap/react"; import StarterKit from "@tiptap/starter-kit"; import Highlight from "@tiptap/extension-highlight"; import Typography from "@tiptap/extension-typography"; +import Placeholder from "@tiptap/extension-placeholder"; interface NoteEditorProps { content: string; @@ -14,7 +14,14 @@ interface NoteEditorProps { export default function NoteEditor({ content, onChange }: NoteEditorProps) { const editor = useEditor({ - extensions: [StarterKit, Highlight, Typography], + extensions: [ + StarterKit, + Highlight, + Typography, + Placeholder.configure({ + placeholder: "Write something...", + }), + ], content, onUpdate: ({ editor }) => { onChange(editor.getHTML()); diff --git a/apps/desktop/src/components/note/SidePanel.tsx b/apps/desktop/src/components/note/SidePanel.tsx index e142ce781f..1b3b6f2617 100644 --- a/apps/desktop/src/components/note/SidePanel.tsx +++ b/apps/desktop/src/components/note/SidePanel.tsx @@ -1,12 +1,17 @@ import { useState } from "react"; import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import { sendChatMessage } from "../../api/noteApi"; +import type { TranscriptBlock } from "../../types"; interface SidePanelProps { transcript: string; + timestamps?: TranscriptBlock[]; } -export default function SidePanel({ transcript }: SidePanelProps) { +export default function SidePanel({ + transcript, + timestamps = [], +}: SidePanelProps) { const [message, setMessage] = useState(""); const [messages, setMessages] = useState< Array<{ text: string; isUser: boolean }> @@ -56,8 +61,23 @@ export default function SidePanel({ transcript }: SidePanelProps) { className="border-b border-gray-200" >
-

실시간 트랜스크립트

-
{transcript}
+ {timestamps.length > 0 ? ( +
+ {timestamps.map((block, index) => ( +
+
+ {block.timestamp} + + {block.speaker} + +
+
{block.text}
+
+ ))} +
+ ) : ( +
{transcript}
+ )}
diff --git a/apps/desktop/src/mocks/data.ts b/apps/desktop/src/mocks/data.ts index ad510ff904..dc39dde1f4 100644 --- a/apps/desktop/src/mocks/data.ts +++ b/apps/desktop/src/mocks/data.ts @@ -1,4 +1,4 @@ -import type { Note, CalendarEvent } from "../types"; +import type { Note, CalendarEvent, TranscriptBlock } from "../types"; // Helper function to create dates relative to today const today = new Date("2024-12-14T00:00:00Z"); @@ -169,6 +169,14 @@ export const mockNotes: Note[] = [ }, ]; +export const mockTranscripts: TranscriptBlock[] = [ + { timestamp: "09:30:00", text: "안녕하세요, 오늘 회의를 시작하겠습니다.", speaker: "김철수" }, + { timestamp: "09:31:15", text: "지난 회의에서 논의된 사항들을 먼저 리뷰해보겠습니다.", speaker: "김철수" }, + { timestamp: "09:33:20", text: "첫 번째 안건은 신규 프로젝트 일정 조정입니다.", speaker: "이영희" }, + { timestamp: "09:35:45", text: "두 번째로 리소스 할당에 대해 이야기해보겠습니다.", speaker: "박지원" }, + { timestamp: "09:38:10", text: "마지막으로 다음 주 마일스톤 설정에 대해 논의하겠습니다.", speaker: "김철수" } +]; + export const mockEvents: CalendarEvent[] = [ { kind: "calendar#event", diff --git a/apps/desktop/src/pages/Home.tsx b/apps/desktop/src/pages/Home.tsx index 5a532ea8f5..d4b8a8acd2 100644 --- a/apps/desktop/src/pages/Home.tsx +++ b/apps/desktop/src/pages/Home.tsx @@ -1,6 +1,5 @@ import { useState } from "react"; import { useNavigate } from "react-router"; - import { mockNotes } from "../mocks/data"; import { UpcomingEvents } from "../components/home/UpcomingEvents"; import { PastNotes } from "../components/home/PastNotes"; @@ -52,15 +51,13 @@ export default function Home() { return (
-
-
- {isNewUser && } - - -
+
+ {isNewUser && } + +
); diff --git a/apps/desktop/src/pages/Note.tsx b/apps/desktop/src/pages/Note.tsx index c8227c261e..a4d8600a0f 100644 --- a/apps/desktop/src/pages/Note.tsx +++ b/apps/desktop/src/pages/Note.tsx @@ -10,6 +10,7 @@ import NoteEditor from "../components/note/NoteEditor"; import { useUI } from "../contexts/UIContext"; import { useNoteState } from "../hooks/useNoteState"; import { useSpeechRecognition } from "../hooks/useSpeechRecognition"; +import { mockTranscripts } from "../mocks/data"; export default function Note() { const { id } = useParams(); @@ -32,6 +33,15 @@ export default function Note() { stopRecording, } = useSpeechRecognition(); + // 시뮬레이션을 위한 샘플 데이터 + const sampleTimestamps = [ + { time: "09:30", text: "안녕하세요, 오늘 회의를 시작하겠습니다." }, + { time: "09:31", text: "지난 회의에서 논의된 사항들을 먼저 리뷰해보겠습니다." }, + { time: "09:33", text: "첫 번째 안건은 신규 프로젝트 일정 조정입니다." }, + { time: "09:35", text: "두 번째로 리소스 할당에 대해 이야기해보겠습니다." }, + { time: "09:38", text: "마지막으로 다음 주 마일스톤 설정에 대해 논의하겠습니다." } + ]; + const handlePauseResumeClick = () => { handlePauseResume(isPaused, resumeRecording, pauseRecording); }; @@ -93,9 +103,9 @@ export default function Note() { {isPanelOpen && ( <> - - - + + + )} diff --git a/apps/web/src/components/layout/header.tsx b/apps/web/src/components/layout/header.tsx index 9bbb1556ba..d8ef7e5c3d 100644 --- a/apps/web/src/components/layout/header.tsx +++ b/apps/web/src/components/layout/header.tsx @@ -1,22 +1,7 @@ -"use client"; - -import { useState, useEffect } from "react"; import Image from "next/image"; import { HeaderButton } from "@/components/ui/header-button"; -import { cn } from "@/lib/utils"; export default function Header() { - const [isScrolled, setIsScrolled] = useState(false); - - useEffect(() => { - const handleScroll = () => { - setIsScrolled(window.scrollY > 0); - }; - - window.addEventListener("scroll", handleScroll); - return () => window.removeEventListener("scroll", handleScroll); - }, []); - return (
@@ -25,12 +10,7 @@ export default function Header() { HYPRNOTE
- +
); diff --git a/apps/web/src/components/ui/header-button.tsx b/apps/web/src/components/ui/header-button.tsx index 0c386c420c..d213deb5cc 100644 --- a/apps/web/src/components/ui/header-button.tsx +++ b/apps/web/src/components/ui/header-button.tsx @@ -44,12 +44,12 @@ export function HeaderButton({ className }: HeaderButtonProps) { variant="outline" size="default" className={cn( - "inline-flex items-center justify-center gap-2 transition-all duration-200 rounded-xl", + "inline-flex items-center justify-center gap-2 transition-all duration-200 rounded-xl border border-gray-300 hover:border-gray-400", { - "bg-gradient-to-br from-[#f97316] to-[#6366f1] text-white border-transparent hover:from-[#f97316] hover:to-[#6366f1] hover:text-white": + "bg-gradient-to-br from-[#f97316] to-[#6366f1] text-white border-transparent hover:from-[#f97316] border border-gray-300 hover:border-gray-400 hover:to-[#6366f1] hover:text-white": isScrolled, }, - className, + className )} > {os === "Windows" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0bfdc58ddf..e4548b8857 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: '@tiptap/extension-highlight': specifier: ^2.10.3 version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-placeholder': + specifier: ^2.10.3 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) '@tiptap/extension-typography': specifier: ^2.10.3 version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) @@ -1512,6 +1515,12 @@ packages: peerDependencies: '@tiptap/core': ^2.7.0 + '@tiptap/extension-placeholder@2.10.3': + resolution: {integrity: sha512-0OkwnDLguZgoiJM85cfnOySuMmPUF7qqw7DHQ+c3zwTAYnvzpvqrvpupc+2Zi9GfC1sDgr+Ajrp8imBHa6PHfA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + '@tiptap/extension-strike@2.10.3': resolution: {integrity: sha512-jYoPy6F6njYp3txF3u23bgdRy/S5ATcWDO9LPZLHSeikwQfJ47nqb+EUNo5M8jIOgFBTn4MEbhuZ6OGyhnxopA==} peerDependencies: @@ -4991,6 +5000,11 @@ snapshots: dependencies: '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/extension-placeholder@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + '@tiptap/extension-strike@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': dependencies: '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) From 525113e7ed0ea0f9ee4467f36e9ef95582fc5a18 Mon Sep 17 00:00:00 2001 From: John Jeong Date: Tue, 17 Dec 2024 09:56:38 +0900 Subject: [PATCH 3/6] home is good. working on note editor --- apps/desktop/src/App.tsx | 2 +- apps/desktop/src/pages/Home.tsx | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index 31aa4fd0eb..058da93e23 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -27,7 +27,7 @@ function App() {
-
+
} /> } /> diff --git a/apps/desktop/src/pages/Home.tsx b/apps/desktop/src/pages/Home.tsx index d4b8a8acd2..0b2df71446 100644 --- a/apps/desktop/src/pages/Home.tsx +++ b/apps/desktop/src/pages/Home.tsx @@ -50,15 +50,10 @@ export default function Home() { }; return ( -
-
- {isNewUser && } - - -
+
+ {isNewUser && } + +
); } From 1409b5abdf39e7fe8dd58ca5410d63ae1ba3beb8 Mon Sep 17 00:00:00 2001 From: John Jeong Date: Tue, 17 Dec 2024 10:28:01 +0900 Subject: [PATCH 4/6] separated note page components --- .../desktop/src/components/note/ChatPanel.tsx | 149 ++++++++++++++++ .../desktop/src/components/note/SidePanel.tsx | 168 +----------------- .../src/components/note/TranscriptPanel.tsx | 33 ++++ apps/desktop/src/pages/Note.tsx | 21 +-- apps/desktop/src/styles/editor.css | 8 + 5 files changed, 200 insertions(+), 179 deletions(-) create mode 100644 apps/desktop/src/components/note/ChatPanel.tsx create mode 100644 apps/desktop/src/components/note/TranscriptPanel.tsx diff --git a/apps/desktop/src/components/note/ChatPanel.tsx b/apps/desktop/src/components/note/ChatPanel.tsx new file mode 100644 index 0000000000..a5b5b4428e --- /dev/null +++ b/apps/desktop/src/components/note/ChatPanel.tsx @@ -0,0 +1,149 @@ +import { useState } from "react"; +import { sendChatMessage } from "../../api/noteApi"; + +interface ChatPanelProps { + transcript: string; +} + +export default function ChatPanel({ transcript }: ChatPanelProps) { + const [message, setMessage] = useState(""); + const [messages, setMessages] = useState< + Array<{ text: string; isUser: boolean }> + >([]); + + const quickActions = [ + { label: "질의응답 사항 정리", action: "SUMMARIZE_QA" }, + { label: "액션 아이템 나열", action: "LIST_ACTIONS" }, + { label: "회의록 요약", action: "SUMMARIZE_MEETING" }, + { label: "팔로우업 이메일 작성", action: "WRITE_EMAIL" }, + { label: "다음 회의 안건 제안", action: "SUGGEST_AGENDA" }, + ]; + + const handleSubmit = async () => { + if (!message.trim()) return; + + setMessages((prev) => [...prev, { text: message, isUser: true }]); + setMessage(""); + + try { + const response = await sendChatMessage(message, transcript); + setMessages((prev) => [...prev, { text: response.text, isUser: false }]); + } catch (error) { + console.error("AI 응답 처리 중 오류:", error); + setMessages((prev) => [ + ...prev, + { text: "죄송합니다. 오류가 발생했습니다.", isUser: false }, + ]); + } + }; + + const adjustTextareaHeight = (e: React.ChangeEvent) => { + const textarea = e.target; + textarea.style.height = "auto"; + textarea.style.height = `${Math.min(textarea.scrollHeight, 72)}px`; + }; + + return ( +
+ {messages.length === 0 && ( +
+
+

AI 어시스턴트에게 물어보세요

+

+ 회의 내용을 분석하고 정리하는데 도움을 드립니다 +

+
+
+ {quickActions.map((action) => ( + + ))} +
+
+ )} + + {messages.length > 0 && ( +
+ {messages.map((msg, index) => ( +
+ {msg.text} +
+ ))} +
+ )} + +
+