From 3f87d51a55154a9193a0d48a45df75248d4e352f Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 15 Dec 2025 14:21:40 -0800 Subject: [PATCH] add jobs database pages (list, detail, edit) --- .../jobs/sections/JobFeaturesSection.svelte | 90 +++++ .../jobs/sections/JobMetadataSection.svelte | 77 +++++ .../sections/JobProficiencySection.svelte | 77 +++++ .../database/jobs/tabs/JobImagesTab.svelte | 163 +++++++++ .../database/jobs/tabs/JobSkillsTab.svelte | 240 +++++++++++++ src/routes/(app)/database/jobs/+page.svelte | 320 ++++++++++++++++++ .../jobs/[granblueId]/+page.server.ts | 29 ++ .../database/jobs/[granblueId]/+page.svelte | 154 +++++++++ .../jobs/[granblueId]/edit/+page.server.ts | 34 ++ .../jobs/[granblueId]/edit/+page.svelte | 201 +++++++++++ 10 files changed, 1385 insertions(+) create mode 100644 src/lib/features/database/jobs/sections/JobFeaturesSection.svelte create mode 100644 src/lib/features/database/jobs/sections/JobMetadataSection.svelte create mode 100644 src/lib/features/database/jobs/sections/JobProficiencySection.svelte create mode 100644 src/lib/features/database/jobs/tabs/JobImagesTab.svelte create mode 100644 src/lib/features/database/jobs/tabs/JobSkillsTab.svelte create mode 100644 src/routes/(app)/database/jobs/+page.svelte create mode 100644 src/routes/(app)/database/jobs/[granblueId]/+page.server.ts create mode 100644 src/routes/(app)/database/jobs/[granblueId]/+page.svelte create mode 100644 src/routes/(app)/database/jobs/[granblueId]/edit/+page.server.ts create mode 100644 src/routes/(app)/database/jobs/[granblueId]/edit/+page.svelte diff --git a/src/lib/features/database/jobs/sections/JobFeaturesSection.svelte b/src/lib/features/database/jobs/sections/JobFeaturesSection.svelte new file mode 100644 index 00000000..185cea2a --- /dev/null +++ b/src/lib/features/database/jobs/sections/JobFeaturesSection.svelte @@ -0,0 +1,90 @@ + + + + + + {#if editMode} + + + + + + + + + + {#if editData.accessory} + + + + + {:else} + + + + {#if job.granblueId} + + {:else} + — + {/if} + + + + {/if} + diff --git a/src/lib/features/database/jobs/sections/JobProficiencySection.svelte b/src/lib/features/database/jobs/sections/JobProficiencySection.svelte new file mode 100644 index 00000000..5f66201e --- /dev/null +++ b/src/lib/features/database/jobs/sections/JobProficiencySection.svelte @@ -0,0 +1,77 @@ + + + + + + {#if editMode} + + + + {:else} + + {#if proficiencyNames[0]} + {proficiencyNames[0]} + {:else} + — + {/if} + + + {#if proficiencyNames[1]} + {proficiencyNames[1]} + {:else} + — + {/if} + + {/if} + + + diff --git a/src/lib/features/database/jobs/tabs/JobImagesTab.svelte b/src/lib/features/database/jobs/tabs/JobImagesTab.svelte new file mode 100644 index 00000000..552a17b7 --- /dev/null +++ b/src/lib/features/database/jobs/tabs/JobImagesTab.svelte @@ -0,0 +1,163 @@ + + + + +
+
+ + Gran + Djeeta + +
+ +
+
+ + {job.name.en} Portrait + + Portrait +
+ +
+ + {job.name.en} Full + + Full +
+ +
+ + {job.name.en} Icon + + Icon + (No gender variant) +
+ +
+ + {job.name.en} Wide + + Wide Banner +
+
+
+ + diff --git a/src/lib/features/database/jobs/tabs/JobSkillsTab.svelte b/src/lib/features/database/jobs/tabs/JobSkillsTab.svelte new file mode 100644 index 00000000..e0622e67 --- /dev/null +++ b/src/lib/features/database/jobs/tabs/JobSkillsTab.svelte @@ -0,0 +1,240 @@ + + + + +
+ {#if skillsQuery.isLoading} +
Loading skills...
+ {:else if skillsQuery.isError} +
Failed to load skills
+ {:else if !skillsQuery.data?.length} +
No skills found for this job
+ {:else} + {#if hasSkills('main')} +
+

Main Skills

+
+ {#each groupedSkills.main as skill} +
+ {skill.name.en} +
+ {skill.name.en} + {#if skill.name.ja} + {skill.name.ja} + {/if} +
+ + {getSkillCategoryName(skill)} + +
+ {/each} +
+
+ {/if} + + {#if hasSkills('sub')} +
+

Subskills

+
+ {#each groupedSkills.sub as skill} +
+ {skill.name.en} +
+ {skill.name.en} + {#if skill.name.ja} + {skill.name.ja} + {/if} +
+ + {getSkillCategoryName(skill)} + +
+ {/each} +
+
+ {/if} + + {#if hasSkills('emp')} +
+

EMP Skills

+
+ {#each groupedSkills.emp as skill} +
+ {skill.name.en} +
+ {skill.name.en} + {#if skill.name.ja} + {skill.name.ja} + {/if} +
+ + {getSkillCategoryName(skill)} + +
+ {/each} +
+
+ {/if} + + {#if hasSkills('base')} +
+

Base Skills

+
+ {#each groupedSkills.base as skill} +
+ {skill.name.en} +
+ {skill.name.en} + {#if skill.name.ja} + {skill.name.ja} + {/if} +
+ + {getSkillCategoryName(skill)} + +
+ {/each} +
+
+ {/if} + {/if} +
+ + diff --git a/src/routes/(app)/database/jobs/+page.svelte b/src/routes/(app)/database/jobs/+page.svelte new file mode 100644 index 00000000..51385ac9 --- /dev/null +++ b/src/routes/(app)/database/jobs/+page.svelte @@ -0,0 +1,320 @@ + + + + + + +
+
+
+ +
+ + {#if jobsQuery.isLoading} +
Loading jobs...
+ {:else if jobsQuery.isError} +
Failed to load jobs
+ {:else} +
+ + + + + + + + + + + + {#each sortedJobs as job (job.id)} + handleRowClick(job)} class="clickable"> + + + + + + + {/each} + +
ImageNameRowProficienciesFeatures
+ {job.name.en} + +
+ {job.name.en} +
+
+ {getJobTierName(job.row)} + +
+ {#if job.proficiency?.[0]} + + {/if} + {#if job.proficiency?.[1]} + + {/if} +
+
+
+ {#if job.masterLevel} + Master + {/if} + {#if job.ultimateMastery} + Ultimate + {/if} + {#if job.accessory} + Accessory + {/if} +
+
+
+ + + {/if} +
+
+ + diff --git a/src/routes/(app)/database/jobs/[granblueId]/+page.server.ts b/src/routes/(app)/database/jobs/[granblueId]/+page.server.ts new file mode 100644 index 00000000..4931a19a --- /dev/null +++ b/src/routes/(app)/database/jobs/[granblueId]/+page.server.ts @@ -0,0 +1,29 @@ +import type { PageServerLoad } from './$types' +import { jobAdapter } from '$lib/api/adapters/job.adapter' +import { error } from '@sveltejs/kit' + +export const load: PageServerLoad = async ({ params, parent }) => { + try { + // Get parent data to access role + const parentData = await parent() + + const job = await jobAdapter.getById(params.granblueId) + + if (!job) { + throw error(404, 'Job not found') + } + + return { + job, + role: parentData.role + } + } catch (err) { + console.error('Failed to load job:', err) + + if (err instanceof Error && 'status' in err && err.status === 404) { + throw error(404, 'Job not found') + } + + throw error(500, 'Failed to load job') + } +} diff --git a/src/routes/(app)/database/jobs/[granblueId]/+page.svelte b/src/routes/(app)/database/jobs/[granblueId]/+page.svelte new file mode 100644 index 00000000..bbb768f8 --- /dev/null +++ b/src/routes/(app)/database/jobs/[granblueId]/+page.svelte @@ -0,0 +1,154 @@ + + + + + + +
+ {#if job} + +
+ + Info + Skills + Images + +
+ + {#if currentTab === 'info'} +
+ + + +
+ {:else if currentTab === 'skills'} + + {:else if currentTab === 'images'} + + {/if} +
+ {:else} +
+

Job Not Found

+

The job you're looking for could not be found.

+ +
+ {/if} +
+ + diff --git a/src/routes/(app)/database/jobs/[granblueId]/edit/+page.server.ts b/src/routes/(app)/database/jobs/[granblueId]/edit/+page.server.ts new file mode 100644 index 00000000..fcac1826 --- /dev/null +++ b/src/routes/(app)/database/jobs/[granblueId]/edit/+page.server.ts @@ -0,0 +1,34 @@ +import type { PageServerLoad } from './$types' +import { jobAdapter } from '$lib/api/adapters/job.adapter' +import { error, redirect } from '@sveltejs/kit' + +export const load: PageServerLoad = async ({ params, parent }) => { + // Get parent data to access role + const parentData = await parent() + + // Role check - must be editor level (>= 7) to edit + if (!parentData.role || parentData.role < 7) { + throw redirect(303, `/database/jobs/${params.granblueId}`) + } + + try { + const job = await jobAdapter.getById(params.granblueId) + + if (!job) { + throw error(404, 'Job not found') + } + + return { + job, + role: parentData.role + } + } catch (err) { + console.error('Failed to load job:', err) + + if (err instanceof Error && 'status' in err && err.status === 404) { + throw error(404, 'Job not found') + } + + throw error(500, 'Failed to load job') + } +} diff --git a/src/routes/(app)/database/jobs/[granblueId]/edit/+page.svelte b/src/routes/(app)/database/jobs/[granblueId]/edit/+page.svelte new file mode 100644 index 00000000..54f1e84e --- /dev/null +++ b/src/routes/(app)/database/jobs/[granblueId]/edit/+page.svelte @@ -0,0 +1,201 @@ + + + + + + +
+ {#if job} + +
+ + + +
+
+ {:else} +
+

Job Not Found

+

The job you're looking for could not be found.

+ +
+ {/if} +
+ +