commit 0be01758e375168b35cb55770b94368354595583 Author: Norbert Maciaszek Date: Fri Dec 26 22:19:47 2025 +0100 init spec diff --git a/gift-app-spec-v1.md b/gift-app-spec-v1.md new file mode 100644 index 0000000..042426e --- /dev/null +++ b/gift-app-spec-v1.md @@ -0,0 +1,420 @@ +# Gift Planning App – MVP Specification + +**Project Name:** Gift Planner +**Created:** December 26, 2025 +**Status:** Pre-development / Discovery Phase + +--- + +## 1. Project Vision & Goals + +### Business Goal +Aplikacja wspomaga planowanie i śledzenie prezentów na dowolne okazje (święta, urodziny, rocznice), automatyzując zarządzanie budżetem, listami osób i śledzeniem cen. + +### Success Metrics (do doprecyzowania) +- Liczba zarejestrowanych userów +- % userów, którzy ukończy workflow od okazji do budżetu +- Engagement z AI recommendations +- Średni czas planowania okazji + +### Ograniczenia na start +- Budżet: TBD +- Deadline MVP: TBD +- Zespół: TBD +- Geograficznie: Polska (Ceneo integration) + +--- + +## 2. Core Domain – MVP Scope + +### User & Authentication +- [ ] Rejestracja / logowanie (email + hasło) +- [ ] Profil usera (opcjonalnie: foto, preferencje powiadomień) +- [ ] **Bez social logins na MVP** +- [ ] Brak współdzielenia list (single-user na MVP) + +### Globalna Lista Osób (User Resource) +Przypisana do usera, reużywalna między okazjami. + +**Pola:** +- `id`, `userId` +- `name` (imię/pseudonim) +- `relation` (np. matka, przyjaciel, partner – dla kontekstu AI) +- `age` (opcjonalnie, dla AI recommendations) +- `interests` (notatki/tagi: sport, gaming, moda itp.) +- `notes` (dowolne notatki) +- `createdAt`, `updatedAt` + +**Operacje:** +- CRUD na osobach +- Lista osób dla danego usera +- Search/filter po nazwie + +--- + +### Okazja (Occasion) +Kontener dla prezentów i budżetu w konkretnym kontekście czasowym. + +**Pola:** +- `id`, `userId` +- `title` (np. "Święta 2025", "Urodziny Anny") +- `description` (opcjonalnie) +- `date` (przybliżona data okazji) +- `totalBudget` (opcjonalnie, całkowity budżet na okazję) +- `status` (draft, planning, shopping, done) +- `createdAt`, `updatedAt` + +**Operacje:** +- CRUD na okazjach +- Lista okazji dla danego usera +- Filtry: aktywne, przeszłe, po dacie + +--- + +### Powiązanie Osoba ↔ Okazja +Tablica łączy osoby z okazjami (wiele-do-wielu). + +**Pola:** +- `id`, `occasionId`, `personId` +- `budgetPerPerson` (opcjonalnie, Budget przydzielony dla tej osoby na tę okazję) +- `notes` (opcjonalnie, specyficzne notatki dla tej osoby w ramach tej okazji) +- `createdAt` + +**Operacje:** +- Dodaj osoby do okazji (można masowo) +- Usuń osobę z okazji +- Edytuj budżet per osoba + +--- + +### Prezent (Gift) +Konkretny prezent przypisany do osoby w ramach okazji. + +**Pola:** +- `id`, `occasionId`, `personId` +- `title` (nazwa prezentu) +- `status` (idea, selected, bought, wrapped, given – lub podobne state machine) +- `price` (cena szacunkowa lub aktualna z Ceneo) +- `budget` (z czego się liczy: czy wlicza się w budżet osoby?) +- `description` (opcjonalnie, szczegóły) +- `url` (opcjonalnie, link do produktu/sklepu) +- `createdAt`, `updatedAt` + +**Operacje:** +- CRUD na prezentach +- Change status prezentu +- Lista prezentów per osoba +- Lista prezentów per okazja (agregat) + +--- + +### Budżet & Postęp (Occasion Analytics) +Obliczone **automatycznie** na podstawie prezentów i okazji. + +**Per Okazja:** +- Całkowity budżet (suma `totalBudget` lub suma `budgetPerPerson` dla wszystkich osób) +- Wydane dotychczas (suma `price` prezentów ze statusem ≥ "selected") +- Pozostały budżet +- % wykorzystania budżetu +- Liczba osób +- Liczba prezentów (total, ready/wrapped, pending) + +**UI Representation:** +- Progress bar: wydane / budżet +- Liczniki: "3 z 5 osób gotowych", "12 z 15 prezentów" +- Alert, jeśli przekraczamy budżet + +--- + +## 3. Secondary Features – Phase 2 (Post-MVP) + +### Price Tracking via Ceneo + +**Architecture:** +- User dodaje `url` do prezentu (dowolny link, np. ceneo.pl/...) +- Backend: cron job (raz dziennie lub częściej) + manualne "refresh" przez UI +- Pobieranie aktualnej ceny z API Ceneo / scrapingiem (Apify) +- Zapis snapshotu ceny do tabeli `PriceSnapshot(giftId, price, timestamp, source)` + +**Pola Gift (extended):** +- `currentPrice` (najniższa cena z ostatniego snapshotu) +- `priceHistory` (relacja do `PriceSnapshot`) +- `priceAlert` (boolean: czy śledzić zmiany cen?) +- `priceAlertThreshold` (opcjonalnie: powiadom, gdy spadnie poniżej X) + +**UI Features:** +- Mini-sparkline / mini-wykres ostatnich 30 dni cen +- Badge: "Najtaniej w 2 tygodniach" lub "Drożej o X%" od średniej +- Alert: "Cena spadła poniżej progu – dobry moment!" + +**Powiadomienia (Phase 2):** +- Email/push alert, gdy cena spadnie poniżej threshold +- Reminder: "Zbliżają się święta – ceny mogą wzrosnąć" +- Scheduled reminder: "Sprawdzaj ceny tego prezentu co 3 dni" + +--- + +### AI Gift Recommendations (Phase 2) + +**Use Case:** +User przychodzi na okazję, widzi osobę w liście, kliknie "Suggest Gifts" → AI generuje 5–10 propozycji z uzasadnieniami. + +**Input Context (AI):** +- Profil osoby: wiek, zainteresowania, relacja +- Okazja: typ, budżet per osoba, pozostały budżet na całą okazję +- Historia: jakie prezenty już kupił/planuje dla tej osoby w historii (unikaj duplikatów) +- Unikalność: weź pod uwagę, jakie prezenty planuje dla innych osób (różnorodność) + +**Output:** +- Lista propozycji: [{ title, category, priceRange, reason, matchScore }] +- Reason: "Lubisz gaming, a wiek sugeruje..." itp. +- Link do szukania: łatwe przejście do Ceneo/Google Shopping + +**Implementacja:** +- LLM (OpenAI API / local Ollama / inne) +- Prompt engineering: struktura context + constraints (budżet, unikalne przedmioty) +- User ręcznie decyduje, co dodać (zero auto-dodawania, pełna kontrola) + +--- + +## 4. Architektura Techniczna (High Level) + +### Tech Stack (Proposed) +- **Frontend:** React 19 + Next.js (App Router) + - Server Components dla list/agregacji + - Client Components dla interaktywnych formularzy + - TanStack Query do synchronizacji danych + +- **Backend:** Node.js / Next.js API Routes lub oddzielny backend (Express/NestJS) + - REST API lub GraphQL (tbd) + - Autentykacja: JWT / session-based + +- **Database:** PostgreSQL (+ Prisma ORM) + - Wersjonowanie: migrations + +- **External Services:** + - Ceneo API / Apify scraper (Phase 2) + - OpenAI API lub self-hosted LLM (Phase 2) + - Email service (e.g., SendGrid, Resend) dla alertów (Phase 2) + +- **Deployment:** TBD (Vercel, self-hosted, AWS, etc.) + +--- + +### Database Schema (Sketch) + +``` +User +├── id (PK) +├── email (UNIQUE) +├── password_hash +├── created_at +└── updated_at + +Person +├── id (PK) +├── user_id (FK) +├── name +├── relation +├── age +├── interests (TEXT / JSON) +├── notes +├── created_at +├── updated_at + +Occasion +├── id (PK) +├── user_id (FK) +├── title +├── description +├── date +├── total_budget +├── status (draft | planning | shopping | done) +├── created_at +├── updated_at + +OccasionPerson (M2M) +├── id (PK) +├── occasion_id (FK) +├── person_id (FK) +├── budget_per_person +├── notes +├── created_at + +Gift +├── id (PK) +├── occasion_id (FK) +├── person_id (FK) +├── title +├── status (idea | selected | bought | wrapped | given) +├── price +├── description +├── url +├── price_alert (BOOLEAN) +├── price_alert_threshold (DECIMAL, optional) +├── created_at +├── updated_at + +PriceSnapshot (Phase 2) +├── id (PK) +├── gift_id (FK) +├── price (DECIMAL) +├── source (e.g., "ceneo", "direct") +├── timestamp +├── created_at + +AIRecommendation (Phase 2, optional logging) +├── id (PK) +├── occasion_id (FK) +├── person_id (FK) +├── prompt_context (JSON) +├── result (JSON - lista propozycji) +├── created_at +``` + +--- + +### API Endpoints (MVP, Sketch) + +#### Auth +- `POST /api/auth/register` → register user +- `POST /api/auth/login` → login user +- `POST /api/auth/logout` → logout + +#### Persons +- `GET /api/persons` → list all persons for logged user +- `POST /api/persons` → create person +- `PUT /api/persons/:id` → update person +- `DELETE /api/persons/:id` → delete person + +#### Occasions +- `GET /api/occasions` → list occasions for logged user +- `POST /api/occasions` → create occasion +- `PUT /api/occasions/:id` → update occasion +- `DELETE /api/occasions/:id` → delete occasion +- `GET /api/occasions/:id` → get occasion with full context + +#### OccasionPerson (Managing persons in occasion) +- `POST /api/occasions/:id/persons` → add person(s) to occasion +- `DELETE /api/occasions/:id/persons/:personId` → remove person +- `PUT /api/occasions/:id/persons/:personId` → update budget_per_person + +#### Gifts +- `GET /api/occasions/:id/gifts` → list gifts for occasion +- `POST /api/occasions/:id/gifts` → create gift for person +- `PUT /api/gifts/:id` → update gift (title, status, price, url, etc.) +- `DELETE /api/gifts/:id` → delete gift + +#### Occasion Analytics (computed read-only) +- `GET /api/occasions/:id/analytics` → budget, postęp, countdowny + +--- + +## 5. UI/UX Flow (MVP) + +### Key Views + +#### 1. Dashboard (Home) +- Welcome message +- List okazji (karty): aktywne vs archiwalne +- Quick stats: ile osób/prezentów do kupienia, budżet całkowity +- Shortcuts: "+ New Occasion", "+ Quick Add Gift" + +#### 2. Okazja Detail (Single Occasion) +- Nagłówek: nazwa, data, budżet, progress bar +- 2 widoki (tabbed): + - **Persons Tab:** lista osób z budżetami, możliwość dodania, usunięcia, edycji budżetu + - **Gifts Tab (list view):** wszystkie prezenty dla okazji, szybka edycja statusu/ceny, agregat budżetu + +#### 3. Osoba Detail (+ Gifts for this Person) +- Info: imię, wiek, zainteresowania, notatki +- Lista prezentów dla tej osoby (w kontekście aktualnej okazji) +- Button: "AI Suggestions" (Phase 2) +- Edycja danych osoby + +#### 4. Gift Detail +- Edycja: nazwa, status, cena, URL, opis +- Link preview (opcjonalnie: og:image) +- Price tracker (Phase 2): mini-chart, alerts +- Delete/Archive + +#### 5. Settings (Simple MVP) +- Profil usera +- Zmiana hasła +- Preferencje powiadomień (Phase 2) +- Logout + +--- + +## 6. MVP Definition & Phasing + +### MVP = Everything in Section 2 (Core Domain) +- ✅ User auth +- ✅ Persons management (global reusable list) +- ✅ Occasions CRUD +- ✅ Connect persons to occasions +- ✅ Gifts CRUD + status tracking +- ✅ Budget & postęp calculations +- ✅ Aggregate gift list per occasion + +**Timeline:** ~4–8 weeks (team-dependent) + +### Phase 2 (Post-MVP, ~4 weeks after) +- Price tracking via Ceneo + PriceSnapshot table +- Price alerts & notifications (email/push) +- AI gift recommendations (LLM integration) + +### Phase 3+ (Nice-to-have, Later) +- Collaborative lists (share occasion with family) +- Analytics: roczne porównania, trendy wydatków +- Export to PDF/calendar +- Mobile app (native or responsive PWA) +- Social: wishlist sharing, gift registry + +--- + +## 7. Key Decisions & Assumptions (To Validate) + +- [ ] Single-user MVP (no collaboration) – OK? +- [ ] Auth method: email/password or OAuth? (assuming email/pwd for MVP) +- [ ] Database: PostgreSQL assumption – confirm? +- [ ] Ceneo integration: API lub web scraping? (Apify fallback) +- [ ] AI model: OpenAI API czy local/self-hosted? (cost/privacy trade-off) +- [ ] Monetization: subscription, freemium, ads? (affects feature gating) +- [ ] Mobile-first design czy desktop-first? (assuming mobile-responsive on MVP) + +--- + +## 8. Next Steps + +1. **Validate domain model** – robi sens struktura User → Occasion → Person → Gift? +2. **Detailed API spec** – co dokładnie zwraca endpoint? +3. **UI wireframes** – sketche ekranów +4. **Phase 1 backlog** – rozbić MVP na user stories + tasking +5. **Tech setup** – inicjalizacja repo, struktura projektu, Prisma schema +6. **First feature cycle** – login/register → Person CRUD → Occasion CRUD + +--- + +## 9. Assumptions & Open Questions + +### Business +- Czy aplikacja ma być darmowa czy z opcjami premium? +- Target audience: Polska czy szerzej? +- Launch timeline? + +### Technical +- Czy self-hosted czy cloud (Vercel, Railway)? +- Rate limits dla Ceneo API czy backup plan? +- Jak long-term archivizować stare okazje? + +### Product +- Czy dark mode na MVP? +- Czy offline support (PWA)? +- Czy mobile app native czy Web + PWA? + +--- + +**Document Version:** 1.0 +**Last Updated:** December 26, 2025 +**Status:** Awaiting validation & feedback