v0.11.0 — Plant types: the reusable "kind" record
A rich-but-all-optional reference record per kind of plant (care, sun, water, bloom & harvest windows, toxic-to-pets, edible parts, spacing), distinct from a specific planting or a group. - PlantType model + optional Plant.plantTypeId; migration + idempotent backfill that seeds 247 kinds from the built-in plant library and links plantings by species/common name (wired into the deploy entrypoint) - /api/plant-types CRUD; new "Plant types" section (browse by category, edit a kind, see every spot you've planted it) - New plants auto-link to their type on create; plant detail shows "More about…" - PlantType added to backup/restore; bump APP_VERSION 0.11.0 + changelog Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,13 @@ export type ChangelogEntry = {
|
||||
};
|
||||
|
||||
export const CHANGELOG: ChangelogEntry[] = [
|
||||
{
|
||||
version: "0.11.0",
|
||||
date: "2026-06-15",
|
||||
changes: [
|
||||
"New \"Plant types\" library — a place to keep general info about each kind of plant (lily of the valley, Honeycrisp apple…): care notes, sun and water needs, bloom and harvest months, whether it's toxic to pets, and more. Every field is optional. Your plants link to their type automatically, so opening a plant now shows \"More about…\" and a type page lists every spot you've planted it.",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "0.10.0",
|
||||
date: "2026-06-15",
|
||||
|
||||
63
src/lib/garden/plant-types.ts
Normal file
63
src/lib/garden/plant-types.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type { PrismaClient } from "@prisma/client";
|
||||
import { PLANT_DB } from "./plant-db";
|
||||
|
||||
// Stable, deterministic id for a library-seeded PlantType so upserts are
|
||||
// idempotent across seed / deploy-backfill / re-runs.
|
||||
function slug(s: string): string {
|
||||
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
||||
}
|
||||
export function libraryTypeId(commonName: string, species?: string | null): string {
|
||||
return `pt-${slug(commonName)}${species ? `-${slug(species)}` : ""}`;
|
||||
}
|
||||
|
||||
export type PlantTypeSyncResult = { types: number; linked: number };
|
||||
|
||||
/**
|
||||
* Idempotently upsert a PlantType for every entry in the built-in plant library
|
||||
* (src/lib/garden/plant-db.ts), then link any Plant lacking a plantTypeId to its
|
||||
* kind — by species first, else common name. `update: {}` so re-runs never
|
||||
* clobber a user's edits to a type. Safe to run repeatedly.
|
||||
*/
|
||||
export async function syncPlantTypesFromLibrary(db: PrismaClient): Promise<PlantTypeSyncResult> {
|
||||
for (const entry of PLANT_DB) {
|
||||
const id = libraryTypeId(entry.commonName, entry.species);
|
||||
await db.plantType.upsert({
|
||||
where: { id },
|
||||
update: {},
|
||||
create: {
|
||||
id,
|
||||
commonName: entry.commonName,
|
||||
species: entry.species ?? null,
|
||||
category: entry.category,
|
||||
careNotes: entry.notes ?? null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const types = await db.plantType.findMany({
|
||||
select: { id: true, commonName: true, species: true },
|
||||
});
|
||||
const bySpecies = new Map<string, string>();
|
||||
const byCommon = new Map<string, string>();
|
||||
for (const t of types) {
|
||||
if (t.species) bySpecies.set(t.species.toLowerCase().trim(), t.id);
|
||||
byCommon.set(t.commonName.toLowerCase().trim(), t.id);
|
||||
}
|
||||
|
||||
const unlinked = await db.plant.findMany({
|
||||
where: { plantTypeId: null },
|
||||
select: { id: true, commonName: true, species: true },
|
||||
});
|
||||
let linked = 0;
|
||||
for (const p of unlinked) {
|
||||
const typeId =
|
||||
(p.species && bySpecies.get(p.species.toLowerCase().trim())) ||
|
||||
byCommon.get(p.commonName.toLowerCase().trim());
|
||||
if (typeId) {
|
||||
await db.plant.update({ where: { id: p.id }, data: { plantTypeId: typeId } });
|
||||
linked++;
|
||||
}
|
||||
}
|
||||
|
||||
return { types: PLANT_DB.length, linked };
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
// Bump on every user-visible release. Changelog entries live in `src/lib/changelog.ts`.
|
||||
export const APP_VERSION = "0.10.0";
|
||||
export const APP_VERSION = "0.11.0";
|
||||
|
||||
Reference in New Issue
Block a user