Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions app/src/components/Calendar/CalendarDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -347,15 +347,15 @@ function WeekView({
return (
<div className="flex-1 flex flex-col min-h-0 overflow-hidden">
{/* Day headers */}
<div className="grid border-b border-gray-200 shrink-0" style={{ gridTemplateColumns: '60px repeat(7, 1fr)' }}>
<div className="grid border-b border-gray-200 shrink-0" style={{ gridTemplateColumns: '40px repeat(7, 1fr)' }}>
<div /> {/* gutter */}
{days.map((d, i) => {
const today = isToday(d);
return (
<div key={i} className="py-2 text-center border-l border-gray-100">
<div className="text-[11px] font-medium text-gray-500 tracking-wide">{DAY_NAMES[i]}</div>
<div key={i} className="py-1 sm:py-2 text-center border-l border-gray-100">
<div className="text-[9px] sm:text-[11px] font-medium text-gray-500 tracking-wide">{DAY_NAMES[i]}</div>
<div
className={`text-2xl mt-0.5 leading-none w-10 h-10 mx-auto flex items-center justify-center rounded-full ${
className={`text-base sm:text-2xl mt-0.5 leading-none w-7 h-7 sm:w-10 sm:h-10 mx-auto flex items-center justify-center rounded-full ${
today ? 'bg-blue-600 text-white font-medium' : 'text-gray-800'
}`}
>
Expand All @@ -368,13 +368,13 @@ function WeekView({

{/* Time grid */}
<div ref={scrollRef} className="flex-1 overflow-y-auto min-h-0">
<div className="relative grid" style={{ gridTemplateColumns: '60px repeat(7, 1fr)' }}>
<div className="relative grid" style={{ gridTemplateColumns: '40px repeat(7, 1fr)' }}>
{/* Time labels */}
<div className="relative">
{HOURS.map((hour) => (
<div key={hour} className="h-[60px] relative">
{hour > 0 && (
<span className="absolute -top-2 right-2 text-[10px] text-gray-400 font-medium">
<span className="absolute -top-2 right-0.5 sm:right-2 text-[8px] sm:text-[10px] text-gray-400 font-medium">
{hour === 12 ? '12 PM' : hour > 12 ? `${hour - 12} PM` : `${hour} AM`}
</span>
)}
Expand Down Expand Up @@ -563,8 +563,8 @@ export function CalendarDetail() {
return (
<div className="h-full flex flex-col bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
{/* ── Toolbar ── */}
<div className="flex items-center justify-between px-4 py-2.5 border-b border-gray-200 bg-white shrink-0">
<div className="flex items-center gap-3">
<div className="flex flex-wrap items-center justify-between gap-2 px-2 sm:px-4 py-2 sm:py-2.5 border-b border-gray-200 bg-white shrink-0">
<div className="flex items-center gap-1.5 sm:gap-3">
{/* Back */}
<button
onClick={() => navigate('/calendars')}
Expand All @@ -577,18 +577,18 @@ export function CalendarDetail() {
</button>

{/* Calendar dot + name */}
<div className="flex items-center gap-2">
<div className="flex items-center gap-1.5 sm:gap-2">
<div className="w-3 h-3 rounded-sm" style={{ backgroundColor: calendar.color }} />
<span className="text-sm font-medium text-gray-700">{calendar.name}</span>
<span className="text-xs sm:text-sm font-medium text-gray-700 truncate max-w-[100px] sm:max-w-none">{calendar.name}</span>
</div>

{/* Divider */}
<div className="w-px h-5 bg-gray-200" />
<div className="w-px h-5 bg-gray-200 hidden sm:block" />

{/* Today button */}
<button
onClick={goToToday}
className="px-3 py-1.5 text-sm font-medium text-gray-700 border border-gray-300 rounded-md hover:bg-gray-50 active:bg-gray-100 transition-colors"
className="px-2 sm:px-3 py-1 sm:py-1.5 text-xs sm:text-sm font-medium text-gray-700 border border-gray-300 rounded-md hover:bg-gray-50 active:bg-gray-100 transition-colors"
>
Today
</button>
Expand All @@ -597,15 +597,15 @@ export function CalendarDetail() {
<div className="flex items-center">
<button
onClick={() => navigatePeriod(-1)}
className="w-8 h-8 flex items-center justify-center rounded-full text-gray-600 hover:bg-gray-100 transition-colors"
className="w-7 h-7 sm:w-8 sm:h-8 flex items-center justify-center rounded-full text-gray-600 hover:bg-gray-100 transition-colors"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>
<button
onClick={() => navigatePeriod(1)}
className="w-8 h-8 flex items-center justify-center rounded-full text-gray-600 hover:bg-gray-100 transition-colors"
className="w-7 h-7 sm:w-8 sm:h-8 flex items-center justify-center rounded-full text-gray-600 hover:bg-gray-100 transition-colors"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
Expand All @@ -614,7 +614,7 @@ export function CalendarDetail() {
</div>

{/* Period label */}
<h2 className="text-lg font-medium text-gray-900 select-none">{headerLabel}</h2>
<h2 className="text-sm sm:text-lg font-medium text-gray-900 select-none">{headerLabel}</h2>
</div>

{/* View switcher */}
Expand All @@ -623,7 +623,7 @@ export function CalendarDetail() {
<button
key={mode}
onClick={() => setViewMode(mode)}
className={`px-3 py-1 text-sm font-medium rounded-md transition-all ${
className={`px-2 sm:px-3 py-1 text-xs sm:text-sm font-medium rounded-md transition-all ${
viewMode === mode
? 'bg-white text-gray-900 shadow-sm'
: 'text-gray-600 hover:text-gray-800'
Expand Down
14 changes: 7 additions & 7 deletions app/src/components/Chat/ChatInterface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export function ChatInterface() {
</button>
</div>

<div className="flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50 relative">
<div className="flex-1 overflow-y-auto p-3 sm:p-4 space-y-3 sm:space-y-4 bg-gray-50 relative">
{isLoadingMessages && (
<div className="absolute inset-0 bg-gray-50 bg-opacity-80 flex items-center justify-center z-10">
<div className="w-8 h-8 border-4 border-blue-200 border-t-blue-600 rounded-full animate-spin" />
Expand All @@ -167,7 +167,7 @@ export function ChatInterface() {
className={`flex ${message.role === 'user' ? 'justify-end' : 'justify-start'}`}
>
<div
className={`max-w-[70%] rounded-lg px-4 py-3 ${
className={`max-w-[85%] sm:max-w-[70%] rounded-lg px-3 sm:px-4 py-2 sm:py-3 ${
message.role === 'user'
? 'bg-blue-600 text-white'
: 'bg-white text-gray-900 shadow-sm border border-gray-200'
Expand Down Expand Up @@ -221,23 +221,23 @@ export function ChatInterface() {
</div>
)}

<div className="bg-white border-t border-gray-200 px-6 py-4">
<div className="flex gap-3">
<div className="bg-white border-t border-gray-200 px-3 sm:px-6 py-3 sm:py-4">
<div className="flex gap-2 sm:gap-3">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type your message..."
disabled={isLoading}
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed"
className="flex-1 px-3 sm:px-4 py-2 text-sm sm:text-base border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed"
/>
<button
onClick={handleSendMessage}
disabled={!inputValue.trim() || isLoading}
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:bg-gray-300 disabled:cursor-not-allowed flex items-center gap-2"
className="px-3 sm:px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:bg-gray-300 disabled:cursor-not-allowed flex items-center gap-2"
>
<span>Send</span>
<span className="hidden sm:inline">Send</span>
<svg
className="w-5 h-5"
fill="none"
Expand Down
64 changes: 38 additions & 26 deletions app/src/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ export function Layout({ children }: LayoutProps) {
const isCalendarDetail = location.pathname.startsWith('/calendar/');

return (
<div className="min-h-screen bg-gray-50 flex flex-col">
<div className="h-screen bg-gray-50 flex flex-col overflow-hidden">
<nav className="bg-white shadow-sm border-b border-gray-200 shrink-0">
<div className="px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center gap-8">
<div className="px-3 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-14 sm:h-16">
<div className="flex items-center gap-4 sm:gap-8">
<div className="flex items-center gap-2 cursor-pointer" onClick={() => navigate('/calendars')}>
<div className="w-8 h-8 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-lg flex items-center justify-center">
<svg
Expand All @@ -53,13 +53,13 @@ export function Layout({ children }: LayoutProps) {
/>
</svg>
</div>
<span className="text-xl font-bold text-gray-900">Calendar Assistant</span>
<span className="text-lg sm:text-xl font-bold text-gray-900 hidden sm:block">Calendar Assistant</span>
</div>

<div className="flex gap-1">
<button
onClick={() => navigate('/calendars')}
className={`flex items-center gap-2 px-4 py-2 rounded-lg transition-colors ${
className={`flex items-center gap-2 px-3 sm:px-4 py-2 rounded-lg transition-colors ${
isActive('/calendars') || isActive('/calendar')
? 'bg-blue-50 text-blue-600 font-medium'
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'
Expand All @@ -78,16 +78,16 @@ export function Layout({ children }: LayoutProps) {
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
<span>Calendars</span>
<span className="hidden sm:inline">Calendars</span>
</button>
</div>
</div>

<div className="flex items-center gap-3">
<div className="flex items-center gap-2 sm:gap-3">
{/* Chat toggle button */}
<button
onClick={() => setChatOpen(!chatOpen)}
className={`flex items-center gap-2 px-4 py-2 rounded-lg transition-colors ${
className={`flex items-center gap-2 px-3 sm:px-4 py-2 rounded-lg transition-colors ${
chatOpen
? 'bg-blue-50 text-blue-600 font-medium'
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'
Expand All @@ -107,14 +107,14 @@ export function Layout({ children }: LayoutProps) {
d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"
/>
</svg>
<span>Assistant</span>
<span className="hidden sm:inline">Assistant</span>
</button>

{/* User menu */}
<div className="relative">
<button
onClick={() => setShowUserMenu(!showUserMenu)}
className="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-gray-50 transition-colors"
className="flex items-center gap-2 sm:gap-3 px-2 sm:px-3 py-2 rounded-lg hover:bg-gray-50 transition-colors"
>
{user?.picture ? (
<img
Expand All @@ -129,11 +129,11 @@ export function Layout({ children }: LayoutProps) {
</span>
</div>
)}
<span className="text-sm font-medium text-gray-700 hidden sm:block">
<span className="text-sm font-medium text-gray-700 hidden md:block">
{user?.name}
</span>
<svg
className={`w-4 h-4 text-gray-400 transition-transform ${
className={`w-4 h-4 text-gray-400 transition-transform hidden sm:block ${
showUserMenu ? 'rotate-180' : ''
}`}
fill="none"
Expand Down Expand Up @@ -188,24 +188,36 @@ export function Layout({ children }: LayoutProps) {
</div>
</nav>

<div className="flex flex-1 overflow-hidden">
<div className="flex flex-1 overflow-hidden relative">
{/* Main content */}
<main className={`flex-1 overflow-y-auto ${isCalendarDetail ? 'px-4 py-4' : 'max-w-7xl mx-auto w-full px-4 sm:px-6 lg:px-8 py-8'}`}>
<main className={`flex-1 overflow-y-auto ${isCalendarDetail ? 'px-2 sm:px-4 py-2 sm:py-4' : 'max-w-7xl mx-auto w-full px-4 sm:px-6 lg:px-8 py-4 sm:py-8'}`}>
{children}
</main>

{/* Collapsible chat panel */}
<div
className={`shrink-0 border-l border-gray-200 bg-white transition-all duration-300 ease-in-out overflow-hidden ${
chatOpen ? 'w-[480px]' : 'w-0'
}`}
>
{chatOpen && (
<div className="w-[480px] h-full">
<ChatInterface />
{/* Chat panel — full-screen overlay on mobile, side panel on desktop */}
{chatOpen && (
<>
{/* Mobile overlay backdrop */}
<div
className="fixed inset-0 bg-black/40 z-30 lg:hidden"
onClick={() => setChatOpen(false)}
/>
<div className="fixed inset-0 z-40 lg:relative lg:inset-auto lg:z-auto lg:w-[480px] lg:shrink-0 lg:border-l lg:border-gray-200 bg-white">
{/* Mobile close button */}
<button
onClick={() => setChatOpen(false)}
className="absolute top-3 right-3 z-50 w-8 h-8 flex items-center justify-center rounded-full bg-gray-100 text-gray-600 hover:bg-gray-200 lg:hidden"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<div className="h-full">
<ChatInterface />
</div>
</div>
)}
</div>
</>
)}
</div>
</div>
);
Expand Down