feat: ship templates, crew fields, and read/edit dashboard
- Add crew_req, hardpoints, cargo fields (DB migration + server + types) - Add 10 ship templates from Appendix A (Caravel, Galleon, Sloop, etc.) - Enhanced CreateShipModal with template picker that auto-fills all stats - Dashboard defaults to compact read-only view; Edit button toggles to editable steppers/dropdowns - New CrewSection showing crew required, hardpoints, and cargo - Two-column form layout in create modal for better use of space - Fix .gitignore data/ pattern to only match root-level data directory Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
3
server/src/db/migrations/003_add_ship_fields.sql
Normal file
3
server/src/db/migrations/003_add_ship_fields.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE ships ADD COLUMN crew_req INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ships ADD COLUMN hardpoints INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE ships ADD COLUMN cargo INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -15,6 +15,9 @@ export interface Ship {
|
||||
maneuver_class: string | null;
|
||||
size_category: string | null;
|
||||
notes: string | null;
|
||||
crew_req: number;
|
||||
hardpoints: number;
|
||||
cargo: number;
|
||||
updated_at: number;
|
||||
}
|
||||
|
||||
@@ -56,8 +59,8 @@ export function createShip(input: CreateShipInput): Ship {
|
||||
const now = Date.now();
|
||||
|
||||
db.prepare(`
|
||||
INSERT INTO ships (id, name, hull_current, hull_max, armor_current, armor_max, ac, con_save, speed, maneuver_class, size_category, notes, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO ships (id, name, hull_current, hull_max, armor_current, armor_max, ac, con_save, speed, maneuver_class, size_category, notes, crew_req, hardpoints, cargo, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
id,
|
||||
input.name,
|
||||
@@ -71,6 +74,9 @@ export function createShip(input: CreateShipInput): Ship {
|
||||
input.maneuver_class,
|
||||
input.size_category,
|
||||
input.notes,
|
||||
input.crew_req,
|
||||
input.hardpoints,
|
||||
input.cargo,
|
||||
now,
|
||||
);
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ export const createShipSchema = z.object({
|
||||
maneuver_class: z.enum(maneuverClasses).nullable().default(null),
|
||||
size_category: z.string().max(50).nullable().default(null),
|
||||
notes: z.string().nullable().default(null),
|
||||
crew_req: z.number().int().min(0).default(0),
|
||||
hardpoints: z.number().int().min(0).default(0),
|
||||
cargo: z.number().int().min(0).default(0),
|
||||
});
|
||||
|
||||
export const updateShipSchema = z
|
||||
@@ -29,6 +32,9 @@ export const updateShipSchema = z
|
||||
maneuver_class: z.enum(maneuverClasses).nullable(),
|
||||
size_category: z.string().max(50).nullable(),
|
||||
notes: z.string().nullable(),
|
||||
crew_req: z.number().int().min(0),
|
||||
hardpoints: z.number().int().min(0),
|
||||
cargo: z.number().int().min(0),
|
||||
})
|
||||
.partial()
|
||||
.refine(
|
||||
|
||||
Reference in New Issue
Block a user