feat: initial backend MVP (auth, habits, village, leaderboard)
This commit is contained in:
parent
f0177d31c0
commit
de30f96c57
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
* text=auto eol=lf
|
||||||
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Nuxt dev/build outputs
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.nuxt
|
||||||
|
.nitro
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
.fleet
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Local env files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
/app/generated/prisma
|
||||||
|
|
||||||
|
prisma/dev.db
|
||||||
109
GEMINI/ARCHITECTURE.md
Normal file
109
GEMINI/ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
# Architecture
|
||||||
|
|
||||||
|
## 1. High-Level Architecture
|
||||||
|
|
||||||
|
The application follows a fullstack SPA architecture:
|
||||||
|
|
||||||
|
- Nuxt 3 frontend
|
||||||
|
- Nitro backend (Node.js)
|
||||||
|
- REST API
|
||||||
|
- MySQL database
|
||||||
|
- Prisma ORM
|
||||||
|
|
||||||
|
Frontend and backend live in a single repository.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Architectural Principles
|
||||||
|
|
||||||
|
- Clear separation of concerns:
|
||||||
|
- UI
|
||||||
|
- State
|
||||||
|
- Domain logic
|
||||||
|
- Persistence
|
||||||
|
- Backend is the source of truth
|
||||||
|
- Frontend does not calculate time-based progression
|
||||||
|
- No real-time connections (WebSockets not required)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Frontend Structure
|
||||||
|
|
||||||
|
- Pages:
|
||||||
|
- Habits
|
||||||
|
- Quests
|
||||||
|
- Village
|
||||||
|
- Leaderboard
|
||||||
|
- Components:
|
||||||
|
- HabitCard
|
||||||
|
- QuestItem
|
||||||
|
- VillageGrid
|
||||||
|
- VillageObject
|
||||||
|
- BuildModeOverlay
|
||||||
|
- State:
|
||||||
|
- userStore
|
||||||
|
- habitsStore
|
||||||
|
- questsStore
|
||||||
|
- villageStore
|
||||||
|
- leaderboardStore
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Backend Structure
|
||||||
|
|
||||||
|
- API routes grouped by domain:
|
||||||
|
- /auth
|
||||||
|
- /user
|
||||||
|
- /habits
|
||||||
|
- /quests
|
||||||
|
- /village
|
||||||
|
- /leaderboard
|
||||||
|
- Domain services:
|
||||||
|
- HabitService
|
||||||
|
- QuestService
|
||||||
|
- VillageService
|
||||||
|
- CropGrowthService
|
||||||
|
- All time-based logic is calculated on request
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Village Logic
|
||||||
|
|
||||||
|
- Village grid is logical (cell-based)
|
||||||
|
- Isometric view is purely visual
|
||||||
|
- Build mode:
|
||||||
|
- shows grid overlay
|
||||||
|
- allows placing, moving and removing objects
|
||||||
|
- View mode:
|
||||||
|
- allows planting and harvesting
|
||||||
|
- Obstacles must be cleared before building
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Time & Progression
|
||||||
|
|
||||||
|
- Server calculates:
|
||||||
|
- whether a quest is available today
|
||||||
|
- whether a crop is grown
|
||||||
|
- streak progression
|
||||||
|
- Time is based on user local date stored on server
|
||||||
|
- No background jobs required for MVP
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Data Flow
|
||||||
|
|
||||||
|
1. Frontend requests current state
|
||||||
|
2. Backend recalculates progression if needed
|
||||||
|
3. Backend returns updated state
|
||||||
|
4. Frontend updates Pinia stores
|
||||||
|
5. UI reflects the new state
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Non-Goals
|
||||||
|
|
||||||
|
- No SSR optimization
|
||||||
|
- No WebSocket connections
|
||||||
|
- No offline mode
|
||||||
|
- No push notifications
|
||||||
156
GEMINI/BUSINESS_REQUIREMENTS.md
Normal file
156
GEMINI/BUSINESS_REQUIREMENTS.md
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
# Business Requirements
|
||||||
|
|
||||||
|
## 1. Product Goal
|
||||||
|
|
||||||
|
Create a mobile-first web application for habit tracking with a light game layer.
|
||||||
|
|
||||||
|
Core idea:
|
||||||
|
Daily habits → quests → rewards → village development → EXP → leaderboard.
|
||||||
|
|
||||||
|
The project is an MVP / pet project.
|
||||||
|
No monetization, no anti-cheat, no social pressure mechanics.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Target Audience
|
||||||
|
|
||||||
|
- Users who want to build daily habits
|
||||||
|
- Users who like visual progress and game mechanics
|
||||||
|
- Mobile users as primary platform
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Core User Loop
|
||||||
|
|
||||||
|
1. User opens the app
|
||||||
|
2. Completes a habit or daily quest
|
||||||
|
3. Receives coins
|
||||||
|
4. Spends coins on village development
|
||||||
|
5. Collects crops and gains EXP
|
||||||
|
6. Sees progress and leaderboard position
|
||||||
|
7. Returns the next day
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Functional Requirements
|
||||||
|
|
||||||
|
### 4.1 User & Profile
|
||||||
|
|
||||||
|
- Registration and login via email + password
|
||||||
|
- One email = one account
|
||||||
|
- Email confirmation is NOT required (MVP)
|
||||||
|
- Profile contains:
|
||||||
|
- public nickname
|
||||||
|
- public avatar
|
||||||
|
- settings:
|
||||||
|
- sound on/off
|
||||||
|
- confetti on/off
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.2 Habits
|
||||||
|
|
||||||
|
- Maximum 3 habits per user
|
||||||
|
- Habit fields:
|
||||||
|
- name (custom or predefined)
|
||||||
|
- active days of week
|
||||||
|
- Habits are:
|
||||||
|
- permanent
|
||||||
|
- editable
|
||||||
|
- removable
|
||||||
|
- Missed days:
|
||||||
|
- are not penalized
|
||||||
|
- shown as red cells in calendar
|
||||||
|
- Completed days:
|
||||||
|
- shown as green cells
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.3 Quests
|
||||||
|
|
||||||
|
#### Habit quests
|
||||||
|
- Can be completed only on active days
|
||||||
|
- Reward: 3 coins per completion
|
||||||
|
|
||||||
|
#### Daily quest
|
||||||
|
- “I visited the site today”
|
||||||
|
- Can be completed once per day
|
||||||
|
- Reward: 1 coin
|
||||||
|
|
||||||
|
#### Streak
|
||||||
|
- 5 consecutive daily visits → +10 coins
|
||||||
|
- Streak resets after reward
|
||||||
|
|
||||||
|
#### UX
|
||||||
|
- Quest completion triggers:
|
||||||
|
- light confetti animation
|
||||||
|
- short success sound
|
||||||
|
- Both effects can be disabled in settings
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.4 Village
|
||||||
|
|
||||||
|
- 2D isometric grid
|
||||||
|
- Grid fits into one mobile screen (no scroll)
|
||||||
|
- Two modes:
|
||||||
|
- view mode
|
||||||
|
- build mode
|
||||||
|
|
||||||
|
#### Objects
|
||||||
|
- House (1 house = 1 worker)
|
||||||
|
- Field
|
||||||
|
- Road
|
||||||
|
- Fence
|
||||||
|
- Obstacles (rocks, bushes, mushrooms)
|
||||||
|
|
||||||
|
#### Rules
|
||||||
|
- Fields cannot exceed number of workers
|
||||||
|
- Removing objects does NOT refund coins
|
||||||
|
- Removing houses blocks building new fields but does not remove existing ones
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.5 Crops & EXP
|
||||||
|
|
||||||
|
- Crop types:
|
||||||
|
- Blueberries
|
||||||
|
- Corn (grows longer)
|
||||||
|
- Growth:
|
||||||
|
- real-time based
|
||||||
|
- no acceleration mechanics
|
||||||
|
- Harvest:
|
||||||
|
- manual
|
||||||
|
- does not expire
|
||||||
|
- Rewards:
|
||||||
|
- harvesting gives EXP
|
||||||
|
- corn additionally gives +1 coin
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.6 Leaderboard
|
||||||
|
|
||||||
|
- Global leaderboard
|
||||||
|
- Period: monthly
|
||||||
|
- Sorted by EXP
|
||||||
|
- Shows:
|
||||||
|
- rank
|
||||||
|
- avatar
|
||||||
|
- nickname
|
||||||
|
- EXP
|
||||||
|
- Equal EXP results in shared ranks
|
||||||
|
(e.g. 1, 2, 2, 2, 3, 4, 5, 5)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. MVP Exclusions
|
||||||
|
|
||||||
|
The MVP explicitly excludes:
|
||||||
|
- donations or payments
|
||||||
|
- levels
|
||||||
|
- progress acceleration
|
||||||
|
- social features
|
||||||
|
- chat
|
||||||
|
- push notifications
|
||||||
|
- anti-cheat
|
||||||
|
- email verification
|
||||||
65
GEMINI/TECH_STACK.md
Normal file
65
GEMINI/TECH_STACK.md
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Technical Stack
|
||||||
|
|
||||||
|
## 1. General Approach
|
||||||
|
|
||||||
|
- Monorepo
|
||||||
|
- Single codebase for frontend and backend
|
||||||
|
- SPA (no SEO requirements)
|
||||||
|
- Mobile-first
|
||||||
|
- Backend used as API and calculation layer
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Frontend
|
||||||
|
|
||||||
|
- Nuxt 3
|
||||||
|
- Vue 3
|
||||||
|
- TypeScript
|
||||||
|
- Pinia (state management)
|
||||||
|
- Vite (build tool)
|
||||||
|
- CSS or Tailwind CSS (implementation choice)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Backend
|
||||||
|
|
||||||
|
- Node.js via Nuxt Nitro
|
||||||
|
- REST API (no GraphQL)
|
||||||
|
- Server-side calculation for:
|
||||||
|
- crop growth
|
||||||
|
- quest availability
|
||||||
|
- streaks
|
||||||
|
- rewards
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Database
|
||||||
|
|
||||||
|
- SQLite
|
||||||
|
- Prisma ORM
|
||||||
|
- Migrations required
|
||||||
|
- Seed data required (initial crops, obstacles, presets)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. State Management
|
||||||
|
|
||||||
|
- Pinia as a single source of truth on frontend
|
||||||
|
- Server is authoritative for:
|
||||||
|
- time-based logic
|
||||||
|
- rewards
|
||||||
|
- progression
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Internationalization
|
||||||
|
|
||||||
|
- i18n support enabled from start
|
||||||
|
- Default language: RU
|
||||||
|
- EN prepared for future use
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Testing
|
||||||
|
|
||||||
|
- Unit tests are NOT required for MVP
|
||||||
214
README.md
Normal file
214
README.md
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
# Smurf Habits
|
||||||
|
|
||||||
|
Habit tracker with a light game layer (village, quests, EXP).
|
||||||
|
Mobile-first web application.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Tech Stack
|
||||||
|
|
||||||
|
- Node.js **20 LTS** (required)
|
||||||
|
- Nuxt **4.x**
|
||||||
|
- Vue 3
|
||||||
|
- Prisma **6.x** (⚠️ NOT 7)
|
||||||
|
- SQLite (development & MVP)
|
||||||
|
- TypeScript
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Environment Requirements
|
||||||
|
|
||||||
|
### Node.js
|
||||||
|
|
||||||
|
**Required:**
|
||||||
|
```
|
||||||
|
Node >= 20.x (LTS)
|
||||||
|
```
|
||||||
|
|
||||||
|
❌ Node 22 / 24 are NOT supported
|
||||||
|
❌ Do not use experimental Node versions
|
||||||
|
|
||||||
|
Check:
|
||||||
|
```bash
|
||||||
|
node -v
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Project Structure
|
||||||
|
|
||||||
|
```text
|
||||||
|
/
|
||||||
|
├─ app/ # UI (pages, components, layouts)
|
||||||
|
├─ server/ # Backend (API, utils, Prisma)
|
||||||
|
│ ├─ api/
|
||||||
|
│ └─ utils/
|
||||||
|
├─ prisma/
|
||||||
|
│ ├─ schema.prisma
|
||||||
|
│ └─ migrations/
|
||||||
|
├─ public/
|
||||||
|
├─ .env
|
||||||
|
├─ nuxt.config.ts
|
||||||
|
└─ README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Important rules
|
||||||
|
|
||||||
|
- `app/` — UI only
|
||||||
|
- `server/` — backend only
|
||||||
|
- `server/` MUST be in project root (not inside `app/`)
|
||||||
|
- Do NOT change this structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Prisma Setup (IMPORTANT)
|
||||||
|
|
||||||
|
### Prisma version
|
||||||
|
|
||||||
|
This project **intentionally uses Prisma 6**.
|
||||||
|
|
||||||
|
❌ Do NOT upgrade to Prisma 7
|
||||||
|
❌ Do NOT use Prisma adapters
|
||||||
|
❌ Do NOT remove `DATABASE_URL`
|
||||||
|
|
||||||
|
Reason:
|
||||||
|
- Prisma 7 has unstable adapter-based API
|
||||||
|
- Prisma 6 is stable and well-supported by Nuxt and tooling
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Prisma schema
|
||||||
|
|
||||||
|
`prisma/schema.prisma` uses classic datasource config:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
datasource db {
|
||||||
|
provider = "sqlite"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Environment variables
|
||||||
|
|
||||||
|
`.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="file:./dev.db"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Prisma workflow
|
||||||
|
|
||||||
|
Whenever you change `schema.prisma`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma migrate dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Never forget migrations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Prisma Client Usage
|
||||||
|
|
||||||
|
Prisma client is initialized here:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
server/utils/prisma.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
export default prisma
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
- Do NOT initialize PrismaClient elsewhere
|
||||||
|
- Do NOT use dynamic imports
|
||||||
|
- Do NOT change this file without a good reason
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Development
|
||||||
|
|
||||||
|
Install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate Prisma client:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
Run dev server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. API Example
|
||||||
|
|
||||||
|
Health check:
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/health
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"usersCount": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Deployment Notes
|
||||||
|
|
||||||
|
- Use Node 20 on hosting
|
||||||
|
- Run Prisma migrations during deployment
|
||||||
|
- SQLite is acceptable for MVP
|
||||||
|
- Database file: `dev.db`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. AI / Gemini Rules (IMPORTANT)
|
||||||
|
|
||||||
|
When using Gemini / AI tools:
|
||||||
|
|
||||||
|
**DO NOT ALLOW:**
|
||||||
|
- changing Node version
|
||||||
|
- upgrading Prisma
|
||||||
|
- changing Prisma configuration
|
||||||
|
- modifying project structure
|
||||||
|
|
||||||
|
**ALLOWED:**
|
||||||
|
- adding models to `schema.prisma`
|
||||||
|
- generating API endpoints
|
||||||
|
- implementing business logic
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Why these constraints exist
|
||||||
|
|
||||||
|
This setup was intentionally chosen to:
|
||||||
|
- avoid unstable Prisma 7 API
|
||||||
|
- keep development predictable
|
||||||
|
- ensure compatibility with Nuxt and Node
|
||||||
|
- prevent tooling-related regressions
|
||||||
|
|
||||||
|
Breaking these rules will likely break the project.
|
||||||
6
app/app.vue
Normal file
6
app/app.vue
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<NuxtRouteAnnouncer />
|
||||||
|
<NuxtWelcome />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
BIN
assets/raw/smurf1.jpg
Normal file
BIN
assets/raw/smurf1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 161 KiB |
BIN
assets/raw/smurf2.jpg
Normal file
BIN
assets/raw/smurf2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 223 KiB |
BIN
assets/raw/smurf3.jpg
Normal file
BIN
assets/raw/smurf3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 140 KiB |
5
nuxt.config.ts
Normal file
5
nuxt.config.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
compatibilityDate: '2025-07-15',
|
||||||
|
devtools: { enabled: true }
|
||||||
|
})
|
||||||
10892
package-lock.json
generated
Normal file
10892
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
package.json
Normal file
19
package.json
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "smurfhabits",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build": "nuxt build",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview",
|
||||||
|
"postinstall": "nuxt prepare"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@prisma/client": "^6.19.1",
|
||||||
|
"nuxt": "^4.2.2",
|
||||||
|
"prisma": "^6.19.1",
|
||||||
|
"vue": "^3.5.26",
|
||||||
|
"vue-router": "^4.6.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
14
prisma.config.ts
Normal file
14
prisma.config.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
// This file was generated by Prisma, and assumes you have installed the following:
|
||||||
|
// npm install --save-dev prisma dotenv
|
||||||
|
import "dotenv/config";
|
||||||
|
import { defineConfig } from "prisma/config";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: "prisma/schema.prisma",
|
||||||
|
migrations: {
|
||||||
|
path: "prisma/migrations",
|
||||||
|
},
|
||||||
|
datasource: {
|
||||||
|
url: process.env["DATABASE_URL"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- Added the required column `password` to the `User` table without a default value. This is not possible if the table is not empty.
|
||||||
|
- Added the required column `updatedAt` to the `User` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Habit" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"daysOfWeek" JSONB NOT NULL,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
"userId" INTEGER NOT NULL,
|
||||||
|
CONSTRAINT "Habit_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "HabitCompletion" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"date" DATETIME NOT NULL,
|
||||||
|
"habitId" INTEGER NOT NULL,
|
||||||
|
CONSTRAINT "HabitCompletion_habitId_fkey" FOREIGN KEY ("habitId") REFERENCES "Habit" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "DailyVisit" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"date" DATETIME NOT NULL,
|
||||||
|
"userId" INTEGER NOT NULL,
|
||||||
|
CONSTRAINT "DailyVisit_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Village" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"userId" INTEGER NOT NULL,
|
||||||
|
CONSTRAINT "Village_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "VillageObject" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"type" TEXT NOT NULL,
|
||||||
|
"x" INTEGER NOT NULL,
|
||||||
|
"y" INTEGER NOT NULL,
|
||||||
|
"obstacleMetadata" TEXT,
|
||||||
|
"cropType" TEXT,
|
||||||
|
"plantedAt" DATETIME,
|
||||||
|
"villageId" INTEGER NOT NULL,
|
||||||
|
CONSTRAINT "VillageObject_villageId_fkey" FOREIGN KEY ("villageId") REFERENCES "Village" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- RedefineTables
|
||||||
|
PRAGMA defer_foreign_keys=ON;
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_User" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"email" TEXT NOT NULL,
|
||||||
|
"password" TEXT NOT NULL,
|
||||||
|
"nickname" TEXT,
|
||||||
|
"avatar" TEXT DEFAULT '/avatars/default.png',
|
||||||
|
"coins" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"exp" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"soundOn" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"confettiOn" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO "new_User" ("createdAt", "email", "id") SELECT "createdAt", "email", "id" FROM "User";
|
||||||
|
DROP TABLE "User";
|
||||||
|
ALTER TABLE "new_User" RENAME TO "User";
|
||||||
|
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
PRAGMA defer_foreign_keys=OFF;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "HabitCompletion_habitId_date_key" ON "HabitCompletion"("habitId", "date");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "DailyVisit_userId_date_key" ON "DailyVisit"("userId", "date");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Village_userId_key" ON "Village"("userId");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "VillageObject_villageId_x_y_key" ON "VillageObject"("villageId", "x", "y");
|
||||||
|
|
@ -1,3 +1,12 @@
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "sqlite"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
// prisma/schema.prisma
|
// prisma/schema.prisma
|
||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
|
|
@ -61,7 +70,7 @@ model Habit {
|
||||||
// This creates a history of the user's progress for each habit.
|
// This creates a history of the user's progress for each habit.
|
||||||
model HabitCompletion {
|
model HabitCompletion {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
date DateTime @db.Date // Store only the date part
|
date DateTime // Store only the date part
|
||||||
|
|
||||||
// Relations
|
// Relations
|
||||||
habit Habit @relation(fields: [habitId], references: [id], onDelete: Cascade)
|
habit Habit @relation(fields: [habitId], references: [id], onDelete: Cascade)
|
||||||
|
|
@ -74,7 +83,7 @@ model HabitCompletion {
|
||||||
// quest and for calculating 5-day streaks.
|
// quest and for calculating 5-day streaks.
|
||||||
model DailyVisit {
|
model DailyVisit {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
date DateTime @db.Date // Store only the date part
|
date DateTime // Store only the date part
|
||||||
|
|
||||||
// Relations
|
// Relations
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
User-Agent: *
|
||||||
|
Disallow:
|
||||||
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./.nuxt/tsconfig.app.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./.nuxt/tsconfig.server.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./.nuxt/tsconfig.shared.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./.nuxt/tsconfig.node.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user