init spec
This commit is contained in:
420
gift-app-spec-v1.md
Normal file
420
gift-app-spec-v1.md
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user