Backend: domain structs, FruitRepository interface + pg implementation,
9 Echo v4 handlers (list/get/create/update/delete, image sub-resources),
migration 000002 (fruit_type ENUM, fruits, fruit_synonyms, fruit_images),
route-scoped BodyLimit("5M") for uploads, http.DetectContentType for serving.
Frontend: typed fetch API layer, Pinia setup-style fruitStore, FruitList
(paginated), FruitCreate, and FruitDetail (edit + synonyms editor + image
gallery). 25 backend unit tests + integration test; 18 frontend tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
46 lines
1.1 KiB
SQL
46 lines
1.1 KiB
SQL
CREATE TYPE fruit_type AS ENUM (
|
|
'Apfelsorten',
|
|
'Birnensorten',
|
|
'Quittensorten',
|
|
'Aprikosen',
|
|
'Pfirsiche',
|
|
'Mirabellen',
|
|
'Renekloden',
|
|
'Pflaumen',
|
|
'Zwetschen',
|
|
'Sauerkirschen',
|
|
'Süßkirschen',
|
|
'Brombeeren',
|
|
'Erdbeeren',
|
|
'Himbeeren',
|
|
'Johannisbeeren',
|
|
'Stachelbeeren',
|
|
'Wein'
|
|
);
|
|
|
|
CREATE TABLE fruits (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
osdb_number VARCHAR(50) NOT NULL UNIQUE,
|
|
comment TEXT,
|
|
fruit_type fruit_type NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE fruit_synonyms (
|
|
id SERIAL PRIMARY KEY,
|
|
fruit_id INTEGER NOT NULL REFERENCES fruits(id) ON DELETE CASCADE,
|
|
synonym VARCHAR(255) NOT NULL
|
|
);
|
|
|
|
CREATE TABLE fruit_images (
|
|
id SERIAL PRIMARY KEY,
|
|
fruit_id INTEGER NOT NULL REFERENCES fruits(id) ON DELETE CASCADE,
|
|
filename VARCHAR(255),
|
|
data BYTEA NOT NULL,
|
|
image_type VARCHAR(20) NOT NULL CHECK (image_type IN ('fruit', 'flower', 'tree')),
|
|
title VARCHAR(255),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|