Features: - HP Control component with damage/heal/direct modes (mobile-optimized) - Conditions system with PF2e condition database - Equipment database with 5,482 items from PF2e (weapons, armor, equipment) - AddItemModal with search, category filters, and pagination - Bulk tracking with encumbered/overburdened status display - Item management (add, remove, toggle equipped) Backend: - Equipment module with search/filter endpoints - Prisma migration for equipment detail fields - Equipment seed script importing from JSON data files - Extended Equipment model (damage, hands, AC, etc.) Frontend: - New components: HpControl, AddConditionModal, AddItemModal - Improved character sheet with tabbed interface - API methods for equipment search and item management Documentation: - CLAUDE.md with project philosophy and architecture decisions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
231 lines
6.7 KiB
TypeScript
231 lines
6.7 KiB
TypeScript
import 'dotenv/config';
|
|
import * as bcrypt from 'bcrypt';
|
|
import { PrismaClient } from '../src/generated/prisma/client.js';
|
|
import { PrismaPg } from '@prisma/adapter-pg';
|
|
|
|
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
|
|
const prisma = new PrismaClient({ adapter });
|
|
|
|
async function main() {
|
|
console.log('Seeding database...\n');
|
|
|
|
// Create password hash
|
|
const passwordHash = await bcrypt.hash('password123', 10);
|
|
|
|
// Create Admin User
|
|
const admin = await prisma.user.upsert({
|
|
where: { email: 'admin@dimension47.local' },
|
|
update: {},
|
|
create: {
|
|
username: 'admin',
|
|
email: 'admin@dimension47.local',
|
|
passwordHash,
|
|
role: 'ADMIN',
|
|
},
|
|
});
|
|
console.log('Created Admin:', admin.username);
|
|
|
|
// Create GM User
|
|
const gm = await prisma.user.upsert({
|
|
where: { email: 'gm@dimension47.local' },
|
|
update: {},
|
|
create: {
|
|
username: 'gamemaster',
|
|
email: 'gm@dimension47.local',
|
|
passwordHash,
|
|
role: 'GM',
|
|
},
|
|
});
|
|
console.log('Created GM:', gm.username);
|
|
|
|
// Create Player Users
|
|
const player1 = await prisma.user.upsert({
|
|
where: { email: 'player1@dimension47.local' },
|
|
update: {},
|
|
create: {
|
|
username: 'spieler1',
|
|
email: 'player1@dimension47.local',
|
|
passwordHash,
|
|
role: 'PLAYER',
|
|
},
|
|
});
|
|
console.log('Created Player:', player1.username);
|
|
|
|
const player2 = await prisma.user.upsert({
|
|
where: { email: 'player2@dimension47.local' },
|
|
update: {},
|
|
create: {
|
|
username: 'spieler2',
|
|
email: 'player2@dimension47.local',
|
|
passwordHash,
|
|
role: 'PLAYER',
|
|
},
|
|
});
|
|
console.log('Created Player:', player2.username);
|
|
|
|
// Create Test Campaign
|
|
const campaign = await prisma.campaign.upsert({
|
|
where: { id: '00000000-0000-0000-0000-000000000001' },
|
|
update: {},
|
|
create: {
|
|
id: '00000000-0000-0000-0000-000000000001',
|
|
name: 'Abendliche Schatten',
|
|
description: 'Eine spannende Kampagne in der Welt von Golarion. Die Helden erkunden uralte Ruinen und stellen sich finsteren Mächten.',
|
|
gmId: gm.id,
|
|
},
|
|
});
|
|
console.log('Created Campaign:', campaign.name);
|
|
|
|
// Add members to campaign
|
|
await prisma.campaignMember.upsert({
|
|
where: { campaignId_userId: { campaignId: campaign.id, userId: gm.id } },
|
|
update: {},
|
|
create: { campaignId: campaign.id, userId: gm.id },
|
|
});
|
|
|
|
await prisma.campaignMember.upsert({
|
|
where: { campaignId_userId: { campaignId: campaign.id, userId: player1.id } },
|
|
update: {},
|
|
create: { campaignId: campaign.id, userId: player1.id },
|
|
});
|
|
|
|
await prisma.campaignMember.upsert({
|
|
where: { campaignId_userId: { campaignId: campaign.id, userId: player2.id } },
|
|
update: {},
|
|
create: { campaignId: campaign.id, userId: player2.id },
|
|
});
|
|
console.log('Added members to campaign');
|
|
|
|
// Create Test Characters
|
|
const character1 = await prisma.character.upsert({
|
|
where: { id: '00000000-0000-0000-0000-000000000101' },
|
|
update: {},
|
|
create: {
|
|
id: '00000000-0000-0000-0000-000000000101',
|
|
campaignId: campaign.id,
|
|
ownerId: player1.id,
|
|
name: 'Thorin Eisenschild',
|
|
type: 'PC',
|
|
level: 3,
|
|
hpCurrent: 38,
|
|
hpMax: 42,
|
|
hpTemp: 0,
|
|
ancestryId: 'dwarf',
|
|
classId: 'fighter',
|
|
backgroundId: 'warrior',
|
|
experiencePoints: 1200,
|
|
},
|
|
});
|
|
console.log('Created Character:', character1.name);
|
|
|
|
// Add abilities for character1
|
|
const abilities1 = [
|
|
{ ability: 'STR' as const, score: 18 },
|
|
{ ability: 'DEX' as const, score: 12 },
|
|
{ ability: 'CON' as const, score: 16 },
|
|
{ ability: 'INT' as const, score: 10 },
|
|
{ ability: 'WIS' as const, score: 14 },
|
|
{ ability: 'CHA' as const, score: 8 },
|
|
];
|
|
|
|
for (const ab of abilities1) {
|
|
await prisma.characterAbility.upsert({
|
|
where: { characterId_ability: { characterId: character1.id, ability: ab.ability } },
|
|
update: { score: ab.score },
|
|
create: { characterId: character1.id, ability: ab.ability, score: ab.score },
|
|
});
|
|
}
|
|
console.log('Added abilities to', character1.name);
|
|
|
|
const character2 = await prisma.character.upsert({
|
|
where: { id: '00000000-0000-0000-0000-000000000102' },
|
|
update: {},
|
|
create: {
|
|
id: '00000000-0000-0000-0000-000000000102',
|
|
campaignId: campaign.id,
|
|
ownerId: player2.id,
|
|
name: 'Elara Sternenlicht',
|
|
type: 'PC',
|
|
level: 3,
|
|
hpCurrent: 24,
|
|
hpMax: 28,
|
|
hpTemp: 0,
|
|
ancestryId: 'elf',
|
|
classId: 'wizard',
|
|
backgroundId: 'scholar',
|
|
experiencePoints: 1200,
|
|
},
|
|
});
|
|
console.log('Created Character:', character2.name);
|
|
|
|
// Add abilities for character2
|
|
const abilities2 = [
|
|
{ ability: 'STR' as const, score: 8 },
|
|
{ ability: 'DEX' as const, score: 14 },
|
|
{ ability: 'CON' as const, score: 12 },
|
|
{ ability: 'INT' as const, score: 18 },
|
|
{ ability: 'WIS' as const, score: 14 },
|
|
{ ability: 'CHA' as const, score: 12 },
|
|
];
|
|
|
|
for (const ab of abilities2) {
|
|
await prisma.characterAbility.upsert({
|
|
where: { characterId_ability: { characterId: character2.id, ability: ab.ability } },
|
|
update: { score: ab.score },
|
|
create: { characterId: character2.id, ability: ab.ability, score: ab.score },
|
|
});
|
|
}
|
|
console.log('Added abilities to', character2.name);
|
|
|
|
// Create an NPC
|
|
const npc = await prisma.character.upsert({
|
|
where: { id: '00000000-0000-0000-0000-000000000201' },
|
|
update: {},
|
|
create: {
|
|
id: '00000000-0000-0000-0000-000000000201',
|
|
campaignId: campaign.id,
|
|
ownerId: null,
|
|
name: 'Meister Aldric',
|
|
type: 'NPC',
|
|
level: 5,
|
|
hpCurrent: 55,
|
|
hpMax: 55,
|
|
hpTemp: 0,
|
|
},
|
|
});
|
|
console.log('Created NPC:', npc.name);
|
|
|
|
// Create a second campaign
|
|
const campaign2 = await prisma.campaign.upsert({
|
|
where: { id: '00000000-0000-0000-0000-000000000002' },
|
|
update: {},
|
|
create: {
|
|
id: '00000000-0000-0000-0000-000000000002',
|
|
name: 'Die verlorene Stadt',
|
|
description: 'Eine Expedition in die legendäre verlorene Stadt Xin-Shalast.',
|
|
gmId: gm.id,
|
|
},
|
|
});
|
|
console.log('Created Campaign:', campaign2.name);
|
|
|
|
await prisma.campaignMember.upsert({
|
|
where: { campaignId_userId: { campaignId: campaign2.id, userId: gm.id } },
|
|
update: {},
|
|
create: { campaignId: campaign2.id, userId: gm.id },
|
|
});
|
|
|
|
console.log('\n✅ Database seeded successfully!');
|
|
console.log('\n📋 Test Accounts:');
|
|
console.log(' Admin: admin@dimension47.local / password123');
|
|
console.log(' GM: gm@dimension47.local / password123');
|
|
console.log(' Player 1: player1@dimension47.local / password123');
|
|
console.log(' Player 2: player2@dimension47.local / password123');
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error('Seeding failed:', e);
|
|
process.exit(1);
|
|
})
|
|
.finally(() => prisma.$disconnect());
|