Skip to content
Merged
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
122 changes: 94 additions & 28 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,42 +32,67 @@ pnpm lint
The app follows a multi-view state machine pattern managed in `app/page.tsx`:

1. **Splash Screen** โ†’ displays for 2.5s on initial load
2. **Login/SignUp** โ†’ authentication views (currently mock, no backend)
2. **Login/SignUp** โ†’ authentication views
3. **Home Calendar** โ†’ main dashboard with calendar and study plan management
4. **PDF Detail View** โ†’ detailed chapter/section view with integrated chatbot
5. **Celebration/Incomplete** โ†’ outcome views based on completion status

State flows between views are controlled by `currentView` state in the root `Home` component.
State flows between views are controlled by `currentView` state in the root `Home` component. Session persistence uses `sessionStorage` with the key `"zeus-auth-session"`.

### Core Data Model

The application revolves around three main types defined in `app/page.tsx`:

- **StudyPlan**: Top-level container for a PDF-based study schedule
- Contains chapters, due date, daily hours, weekend settings
- Links to backend via `learningSourceId`
- Tracks overall progress across all chapters

- **Chapter**: Represents a major section of study material
- Contains multiple sections, scheduled date, completion status
- Estimated time in minutes for completion
- Contains multiple sections (tasks), scheduled date, completion status
- Maps to backend `ChapterInfoDto` structure

- **Section**: Smallest unit of study content
- Contains actual content, key points, definitions
- Individual completion tracking
- **Section**: Smallest unit of study content (called "Task" in backend)
- Contains title, content, completion status
- Corresponds to backend `TaskInfoDto`

### Backend API Integration

The app integrates with a REST API via `lib/api/` modules:

**API Client** (`lib/api/client.ts`):
- Base client using `fetch` with error handling
- Reads `NEXT_PUBLIC_API_BASE_URL` from environment variables
- Custom `ApiError` class for structured error responses
- `apiFetch<T>()` wrapper for type-safe API calls

**API Modules**:
- `auth.ts` - Login and signup endpoints
- `home.ts` - Fetches user's study plans and chapters from `/api/home/{userId}`
- `schedule.ts` - Creates/regenerates schedules with PDF upload (`/api/schedule`, `/api/schedule/reschedule`)
- `study.ts` - Task summary management and completion status updates

**Data Flow**:
1. Home view loads: `fetchHomeData()` โ†’ `mapHomeDataToStudyPlans()` converts DTOs to StudyPlan objects
2. PDF upload: `createSchedule()` sends multipart form data (PDF file + JSON request)
3. Task completion: `updateTaskCompletionStatus()` patches individual task status
4. Summary generation: `createTaskSummary()` and `fetchTaskSummary()` handle AI-generated study content

### Component Architecture

**Main Views** (in `/components`):
- `splash-screen.tsx` - Animated loading screen
- `login-page.tsx` / `signup-page.tsx` - Authentication (mock)
- `login-page.tsx` / `signup-page.tsx` - Authentication forms
- `home-calendar.tsx` - Calendar UI with drag-drop scheduling, sidebar with study plan list
- `pdf-detail-view.tsx` - Three-panel layout (TOC, content, chatbot)
- `pdf-upload-modal.tsx` - Multi-step wizard for PDF upload and plan creation
- `celebration-page.tsx` / `incomplete-page.tsx` - Completion outcome views

**Key Interactions**:
- Study plans are managed in the root `Home` component state
- Study plans are fetched from backend on home view mount via `useEffect` hook in `app/page.tsx:131-149`
- Calendar view supports drag-and-drop chapter rescheduling
- PDF detail view has collapsible sidebar, section navigation, and integrated chatbot
- Chatbot (`chatbot.tsx`) provides context-aware assistance based on current chapter/section
- Progress calculation triggers view transitions to celebration/incomplete pages based on completion and due date

### UI Components

Expand All @@ -80,31 +105,38 @@ This project uses shadcn/ui with the "new-york" style variant. Configuration is
### State Management

No global state management library is used. State is lifted to appropriate parent components:
- Root state in `app/page.tsx`: study plans, current view, modal visibility
- Root state in `app/page.tsx`: study plans (from API), current view, modal visibility, session status
- Local state in views: calendar date, selected items, UI toggles
- Backend serves as source of truth for study plans and task data

### Styling

- Tailwind CSS v4.1.9 with PostCSS
- Custom font: Pretendard (loaded from CDN in `app/layout.tsx`)
- Theme: Uses CSS variables for color scheme
- Responsive design with mobile considerations (hooks/use-mobile.ts)
- Responsive design with mobile considerations (`hooks/use-mobile.ts`)
- Animations via `tailwindcss-animate` and `tw-animate-css`

## Key Technical Notes

### Next.js Configuration

- TypeScript build errors are ignored (`ignoreBuildErrors: true`)
- TypeScript build errors are ignored (`ignoreBuildErrors: true` in `next.config.mjs`)
- Images are unoptimized (`images.unoptimized: true`)
- Uses Next.js App Router (app directory structure)
- All components use `"use client"` directive (fully client-side)
- All components use `"use client"` directive (fully client-side rendered)

### Environment Variables

Required environment variable:
- `NEXT_PUBLIC_API_BASE_URL` - Backend API base URL (e.g., `http://localhost:8080`)

### Date Handling

- Uses native Date objects and `date-fns` library
- Dates are stored as ISO strings in state
- Dates are stored as ISO strings (YYYY-MM-DD format) in state and API
- Calendar calculations in `home-calendar.tsx` use Date arithmetic
- Backend DTOs use `studyDate` field in ISO format

### Form Handling

Expand All @@ -113,18 +145,30 @@ No global state management library is used. State is lifted to appropriate paren

### PDF Processing

Currently **mock implementation only**:
- PDF upload is simulated (no actual parsing)
- Chapter/section data is hardcoded in `app/page.tsx`
- Upload modal (`pdf-upload-modal.tsx`) shows progress simulation
- Future integration point for real PDF parsing would be in the upload modal's `handleGenerate` function
**Current implementation**:
- PDF upload sends actual file to backend via `createSchedule()` in `lib/api/schedule.ts`
- Backend processes PDF and returns structured chapters/tasks
- Upload modal (`pdf-upload-modal.tsx`) handles multipart form submission
- Schedule regeneration available via `reCreateSchedule()` for existing learning sources

### API Error Handling

### Chatbot
All API functions throw `ApiError` instances with:
- `status`: HTTP status code (0 for network errors)
- `message`: User-friendly error message (in Korean)
- `code`: Optional backend error code
- `details`: Raw error data from backend

- Basic mock chatbot implementation in `components/chatbot.tsx`
- Pattern-based response generation (no AI backend)
- Context-aware of current chapter/section
- Integration point for real AI would be in `handleSend` function
Components should catch `ApiError` and display appropriate messages to users.

### Backend Data Mapping

The `mapHomeDataToStudyPlans()` function in `app/page.tsx:48-101` transforms backend DTOs:
- `LearningSourceResponseDto` โ†’ `StudyPlan`
- `ChapterInfoDto` โ†’ `Chapter`
- `TaskInfoDto` โ†’ `Section`
- Scheduled dates are derived from earliest task date in each chapter
- Due date is calculated from latest chapter date

## File Organization

Expand All @@ -135,14 +179,20 @@ app/
globals.css # Global styles, CSS variables

components/
*-page.tsx # Full-page views (login, signup, splash)
*-page.tsx # Full-page views (login, signup, splash, celebration, incomplete)
home-calendar.tsx # Main calendar dashboard
pdf-*.tsx # PDF-related components (upload, detail view)
chatbot.tsx # AI assistant component
ui/ # shadcn/ui component library

lib/
utils.ts # Utility functions (cn() for class merging)
api/
client.ts # Base API client with error handling
auth.ts # Authentication endpoints
home.ts # Home data fetching
schedule.ts # Schedule creation/regeneration
study.ts # Task summary and completion APIs

hooks/
use-mobile.ts # Mobile detection hook
Expand Down Expand Up @@ -170,6 +220,21 @@ const updatedPlans = studyPlans.map(plan =>
)
```

### API Call Pattern

Use try-catch with ApiError handling:
```typescript
try {
const response = await fetchHomeData()
// handle success
} catch (error) {
if (error instanceof ApiError) {
// show user-friendly error message
console.error(error.message)
}
}
```

### Conditional Rendering

Uses ternary operators and conditional chaining extensively:
Expand All @@ -180,8 +245,9 @@ Uses ternary operators and conditional chaining extensively:

## Important Context

- This is a hackathon project (path includes "AI:Hackathon")
- This is a hackathon project (path includes "AI-Hackathon")
- Korean language UI (`lang="ko"` in layout)
- Built with v0.app (noted in metadata generator field)
- Uses Vercel Analytics for tracking
- No backend currently - all data is client-side mock data
- Backend API integration is active (no longer mock data)
- Session management uses sessionStorage (not persistent across browser restarts)
22 changes: 19 additions & 3 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export default function Home() {
const [currentView, setCurrentView] = useState<AppView>("splash")
const [showUploadModal, setShowUploadModal] = useState(false)
const [selectedPlan, setSelectedPlan] = useState<StudyPlan | null>(null)
const [selectedChapterId, setSelectedChapterId] = useState<string | null>(null)
const [studyPlans, setStudyPlans] = useState<StudyPlan[]>([])
const [homeLoaded, setHomeLoaded] = useState(false)
const [homeError, setHomeError] = useState<string | null>(null)
Expand Down Expand Up @@ -148,9 +149,18 @@ export default function Home() {
load()
}, [currentView, homeLoaded])

const handlePlanCreated = (newPlan: StudyPlan) => {
const handlePlanCreated = async (newPlan: StudyPlan) => {
setStudyPlans([...studyPlans, newPlan])
setShowUploadModal(false)

// PDF ์ƒ์„ฑ ํ›„ ํ™ˆ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์™€์„œ ์‹ค์ œ learningSourceId ๋ฐ˜์˜
try {
const res = await fetchHomeData()
const plans = mapHomeDataToStudyPlans(res.data)
setStudyPlans(plans)
} catch (error: any) {
console.error("Failed to reload home data after plan creation", error)
}
}

const handlePlanUpdate = (updatedPlan: StudyPlan) => {
Expand Down Expand Up @@ -181,8 +191,9 @@ export default function Home() {
}
}

const handleViewPdf = (plan: StudyPlan) => {
const handleViewPdf = (plan: StudyPlan, chapterId?: string) => {
setSelectedPlan(plan)
setSelectedChapterId(chapterId || null)
setCurrentView("pdf-detail")
}

Expand Down Expand Up @@ -255,7 +266,12 @@ export default function Home() {
onLogout={handleLogout}
/>
) : selectedPlan ? (
<PdfDetailView plan={selectedPlan} onBack={() => setCurrentView("home")} onUpdatePlan={handlePlanUpdate} />
<PdfDetailView
plan={selectedPlan}
initialChapterId={selectedChapterId}
onBack={() => setCurrentView("home")}
onUpdatePlan={handlePlanUpdate}
/>
) : null}

<PdfUploadModal open={showUploadModal} onOpenChange={setShowUploadModal} onPlanCreated={handlePlanCreated} />
Expand Down
Loading
Loading