New README with up to date informations

This commit is contained in:
2026-07-25 20:56:33 +02:00
parent 0d4688da4d
commit 6baeb54061

288
README.md
View File

@ -1,20 +1,278 @@
# Gyoza (gyoza2)
# Gyoza
HFSPlay stock management
> Inventory and issue tracking for an arcade machine restoration organization (HFSPlay).
## TODO
- [ ] fix style
- [x] handle file upload
- [ ] editable categories
- [x] qrcode generation
- [x] fix search to be persistent
- [x] fix comments to be more legible
- [ ] fix comments to allow resolution
- [ ] batch print QR codes
- [x] fix tables pagination
A single-page application built with **Quasar Framework (Vue 3)** on the frontend and **PocketBase** as the backend. Gyoza replaces a previous Firebase-based version and provides a comprehensive system for cataloging, managing, and tracking items (machines, accessories) with per-item event history and task management.
## Ideas
---
### For real production
## Architecture
Add auto backup to a remote minio server
```
┌──────────────────────────────────────────────────────┐
│ Gyoza Architecture │
├──────────────────────────────────────────────────────┤
│ │
│ Browser (SPA) │
│ ┌──────────────────────────────────────────────┐ │
│ │ Quasar Framework (Vue 3 + Vite) │ │
│ │ ├── Vuex Store (core module) │ │
│ │ ├── Vue Router (hash mode) │ │
│ │ ├── Quasar Plugins (Dialog, Notify, etc.) │ │
│ │ ├── PocketBase JS SDK (superuser auth) │ │
│ │ └── QRCode / Image Compression │ │
│ └──────────────────────────────────────────────┘ │
│ │ │
│ │ HTTP REST API │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ PocketBase Server (Go binary) │ │
│ │ ├── SQLite Database (pb_data/data.db) │ │
│ │ │ ├── categories │ │
│ │ │ ├── stock (unique ref, short_id) │ │
│ │ │ └── history (ref index, file uploads) │ │
│ │ ├── File Storage (history images) │ │
│ │ └── pb_migrations (schema versioning) │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ Auth: SHA-256 credential check (UI gate) + │
│ PocketBase superuser for all API calls │
│ │
└──────────────────────────────────────────────────────┘
```
---
## Tech Stack
| Layer | Technology |
|---|---|
| **Framework** | Quasar v2.16 (Vue 3.4, Composition & Options API) |
| **Routing** | Vue Router 4 (hash mode) |
| **State** | Vuex 4 |
| **Backend** | PocketBase v0.26.1 (Go binary, SQLite, REST API, file storage) |
| **Storage** | SQLite (`pb_data/data.db`) + file storage for images |
| **Build** | Vite via `@quasar/app-vite` |
| **Lint** | ESLint (Standard + Vue 3 Essential) |
| **Key Libs** | `pocketbase` SDK, `qrcode`, `browser-image-compression`, `axios` |
---
## Features
### Authentication
- Custom frontend login with SHA-256 credential verification
- Credentials persisted in `localStorage`
- Router guard redirects unauthenticated users to login
- Separate from PocketBase auth (which uses hardcoded superuser credentials for all API calls)
### Dashboard (`/dashboard`)
- **Global Search** — search items by reference (`ref`) or name (minimum 3 characters). Query persists in the URL.
- **Activity Feed** — last 15 history entries across all items, with relative timestamps and links to the associated item.
### Category Browsing (`/category/:categoryCode`)
- Paginated, sortable table of all items in a category
- Columns: Reference, Name, Condition, Working, In Stock, Owner, Deleted
- Toggle to show/hide soft-deleted items
- In-table search with URL-persisted query
- Condition state shown as a colored chip:
- **Neuf** (green), **Excellent** (green), **Bon** (lime), **Moyen** (orange), **Abimé** (red), **Inutilisable** (black)
- "Add Item" button per category in the sidebar generates the next sequential reference (e.g., `CONS-0004`)
### Item Detail (`/item/:itemRef`)
- **Edit fields:** Name, Owner, Cosmetic Condition, Working (true/false/null), In Stock (available), Deleted (soft delete), Comment
- **QR Code generation** — generates a QR code encoding the item's URL, previewable in a dialog and printable in a new window
- **History timeline** — chronological list of all events/comments for the item:
- Add new entries as either **Info** (comment) or **Task** (issue)
- Upload photos with client-side compression (browser-image-compression, max 1MB, 2000px)
- Click an entry to see full details, photos, and metadata
- Mark tasks as resolved (records `solved_at` and `solved_by`)
- Delete entries with a confirmation dialog
### Item Detail (short ID) (`/:shortId`)
- Short numeric IDs can be used to access an item directly (extracted from QR codes)
- Automatically resolves the `short_id` to the full `ref` and redirects
### Tasks (`/tasks`)
- Consolidated view of all issue-type history entries across all items
- Shows item context (category, name, reference) per task
- Mark tasks as done directly
- Delete tasks
- Navigate to the associated item
### Print Settings (`/print-settings`)
- Preview layout with configurable columns and rows (grid)
- Adjustable gap between cells
- A4 print page generation with QR codes + item names for the latest 24 items
- Generates batched QR code sheets in a printable HTML page
### Sidebar Navigation
- Category list with item counts (the latest sequential reference number per category)
- Quick-add button per category
- **Utilitaires** section: Tasks and Print shortcuts
### User Identity
- On first visit after login, the app prompts for a display name (pseudo)
- Stored in `localStorage` and displayed in the header
- Used as the author for history entries and task resolutions
---
## Database Schema
### `categories` collection
| Field | Type | Description |
|---|---|---|
| `id` | text (PK) | Auto-generated |
| `code` | text | Short code (e.g., `CONS`, `ACC`) |
| `name` | text | Display name (e.g., `Console`, `Accessoire`) |
| `created` / `updated` | autodate | Timestamps |
### `stock` collection
| Field | Type | Description |
|---|---|---|
| `id` | text (PK) | Auto-generated |
| `ref` | text (unique) | Sequential reference (e.g., `CONS-0001`) |
| `short_id` | number | Numeric short ID for QR codes |
| `name` | text | Item name |
| `type` | text | Category name (e.g., `Console`) |
| `state` | text | Condition: `Neuf`, `Excellent`, `Bon`, `Moyen`, `Abimé`, `Inutilisable` |
| `working` | bool/null | Functional status (true/false/null) |
| `available` | bool | Currently in stock |
| `owner` | text | Owner (default: `HFS`) |
| `comment` | text | Free-form notes |
| `deleted` | bool | Soft delete flag |
| `created` / `updated` | autodate | Timestamps |
### `history` collection
| Field | Type | Description |
|---|---|---|
| `id` | text (PK) | Auto-generated |
| `ref` | text (indexed) | References `stock.ref` |
| `type` | select | `comment` or `issue` |
| `text` | text | Event description |
| `user` | text | Display name of the author |
| `date` | date | Event date |
| `image_file` | file | Uploaded photo (thumb: 300x300f, max 1 file) |
| `image` | text | Legacy Firebase image name |
| `solved_at` | date | When the issue was resolved |
| `solved_by` | text | Who resolved the issue |
| `created` / `updated` | autodate | Timestamps |
---
## Getting Started
### Prerequisites
- **Node.js** >= 16
- **pnpm** (recommended) or npm
- PocketBase binary (place `pocketbase` in `./pocketbase/`)
### Installation
```bash
# Install dependencies
pnpm install
# Start PocketBase (in a separate terminal)
./pocketbase/pocketbase serve --dir ./pocketbase/pb_data
# Start the development server
pnpm dev
```
The frontend runs on `http://localhost:9000` and connects to PocketBase at `http://127.0.0.1:8090` in development, or `https://stock.hfsplay.fr` in production (see `src/boot/pocketbase.js`).
### Production Build
```bash
pnpm build
```
Output goes to `dist/spa/`.
---
## Scripts
Data migration scripts are located in `scripts/`:
| Script | Purpose |
|---|---|
| `import_categories.js` | Import categories from legacy Firebase JSON backup |
| `import_stock.js` | Import stock items from legacy Firebase JSON backup |
| `import_history.js` | Import history entries from legacy Firebase JSON backup |
| `import_history_files.js` | Upload historical images to PocketBase storage (with sharp compression) |
| `renumerate.js` | Re-assign sequential `short_id` values to all stock items |
---
## Project Structure
```
gyoza2/
├── pocketbase/ # PocketBase backend
│ ├── pb_data/ # SQLite DB + storage (gitignored)
│ └── pb_migrations/ # Schema migration files (9 migrations)
├── src/
│ ├── boot/ # Startup files (pocketbase.js, helper.js)
│ ├── components/ # Feed.vue, GlobalSearch.vue
│ ├── css/ # Global styles + Geist font
│ ├── layouts/ # DefaultLayout.vue, FullscreenLayout.vue
│ ├── pages/ # Dashboard, StockItem, StockItems, TasksPage, PrintSettings, Index
│ ├── router/ # Route definitions (hash mode)
│ └── store/core/ # Vuex module (state, actions, mutations)
├── scripts/ # Data migration utilities
├── public/ # Static assets (icons, fonts, logos)
├── quasar.config.js # Quasar build configuration
└── package.json
```
---
## Key Design Decisions
- **Superuser-as-client:** PocketBase SDK authenticates as a superuser in the browser. All API calls have full privileges; the frontend login is a UI-level gate only. This simplifies permissions but the superuser credentials are hardcoded in source files.
- **Full data load:** All collections are loaded into Vuex on startup via `getFullList()`. There is currently no real-time subscription or incremental sync.
- **Hash routing:** The app uses `hash` mode for Vue Router, meaning all URLs are client-side (`/#/dashboard`, etc.). This avoids server-side routing requirements.
- **Soft delete:** Items are never truly deleted from the database — the `deleted` boolean flag hides them from normal views.
- **French UI:** The entire user interface is in French.
---
## Roadmap & Technical Debt
### Security (high priority)
- [ ] **Remove hardcoded superuser credentials** from `src/boot/pocketbase.js` — the password is exposed in every browser. Move to server-side proxy or use PocketBase's built-in auth with proper user records and row-level collection rules.
- [ ] **Replace the dual-auth system** — the SHA-256 credential check on the frontend is a UI-only gate while PocketBase superuser creds power the API. Unify into a single PocketBase user auth flow so row-level security can be enforced.
- [ ] **Move credential hash to environment variables** — the hardcoded hash in `src/boot/helper.js` should not live in source.
### Scalability & Performance
- [ ] **Replace client-side filtering/pagination with server-side queries**`StockItems.vue` loads all records then paginates in the browser. Switch to PocketBase's `getList()` with `page`/`perPage` params and server-side `filter`/`sort` strings.
- [ ] **Avoid full `getFullList()` on every navigation**`loadAppData()` fetches all collections each time a page mounts. Implement caching or differential loading.
- [ ] **Re-enable real-time subscriptions** — there is commented-out Firebase realtime code in `DefaultLayout.vue`. PocketBase supports realtime SSE subscriptions; use `pb.collection('stock').subscribe('*', ...)` and `pb.collection('history').subscribe('*', ...)` to incrementally update Vuex.
### Architecture & Refactoring
- [ ] **Renamme Vuex state keys from `firebase`** — the store still uses `state.firebase.categories`, `state.firebase.stock`, `state.firebase.history` as legacy names. Rename to something meaningful (e.g., `state.data`, `state.collections`).
- [ ] **Add a database relation between `history.ref` and `stock`** — currently `history.ref` is a plain text field with only an index. Convert to a PocketBase relation field for proper referential integrity and expand queries.
- [ ] **Clean up unused boilerplate files**`EssentialLink.vue`, `IndexPage.vue`, `Error404.vue`, `ErrorNotFound.vue`, `MainLayout.vue`, `store/module-example/`.
- [ ] **Add proper error handling on all API calls** — most `dispatch` calls in components have `.then()` without a `.catch()`. Network failures or API errors will fail silently.
- [ ] **Add TypeScript support** — the project already has `types.d.ts`, `store-flag.d.ts`, and `jsconfig.json`. Migrate incrementally to `lang="ts"` in Vue SFCs.
### Features
- [ ] **Editable categories** — categories are currently imported via script and cannot be managed through the UI.
- [ ] **Batch print QR codes** with selectable items and configurable grid layout (Print Settings page currently disabled in sidebar).
- [ ] **Resolvable comments** — allow marking non-issue history entries as addressed/resolved.
- [ ] **Bulk operations** — multi-select items for batch edit (e.g., bulk owner change, bulk state update).
- [ ] **Export inventory to CSV/PDF** — generate reports of current stock.
- [ ] **Search by `issue` status** — filter tasks page by open/closed state.
- [ ] **Image gallery per item** — the history list already shows photo thumbnails; add a dedicated gallery view for an item's images.
- [ ] **Item duplication** — clone an existing item (without history) as a quick way to add similar entries.
- [ ] **Remote backup** — auto-backup PocketBase SQLite database and storage files to MinIO or S3.
### UI / UX
- [ ] **Fix Print Settings page** — the sidebar link has `disable` and the page has no way to select which items to print.
- [ ] **Persistent sidebar state**`leftDrawer` opens by default on every page load. Persist the open/closed preference in `localStorage`.
- [ ] **Loading/empty states** — many views show raw empty arrays during initial load rather than skeleton loaders or empty-state placeholders.
- [ ] **Mobile responsiveness** — the 2-column layout on `StockItem.vue` stacks to a single column below `lg` breakpoint, but the table and sidebar could use further mobile polish.
- [ ] **Fix style inconsistencies** — various styling issues noted in commit history and original TODO.