use job mutations and fix skill removal payload
This commit is contained in:
parent
396a02cfe7
commit
2c2580fba3
6 changed files with 48 additions and 72 deletions
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
"job_selection_title": "Select Job",
|
"job_selection_title": "Select Job",
|
||||||
"job_selection_search_placeholder": "Search jobs...",
|
"job_selection_search_placeholder": "Search jobs...",
|
||||||
|
"job_choose": "Choose a job",
|
||||||
|
|
||||||
"skill_selection_title": "Select Skill",
|
"skill_selection_title": "Select Skill",
|
||||||
"skill_selection_search_placeholder": "Search skills...",
|
"skill_selection_search_placeholder": "Search skills...",
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
"job_selection_title": "ジョブ選択",
|
"job_selection_title": "ジョブ選択",
|
||||||
"job_selection_search_placeholder": "ジョブを検索...",
|
"job_selection_search_placeholder": "ジョブを検索...",
|
||||||
|
"job_choose": "ジョブを選択",
|
||||||
|
|
||||||
"skill_selection_title": "スキル選択",
|
"skill_selection_title": "スキル選択",
|
||||||
"skill_selection_search_placeholder": "スキルを検索...",
|
"skill_selection_search_placeholder": "スキルを検索...",
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,9 @@ export class PartyAdapter extends BaseAdapter {
|
||||||
return this.request<Party>(`/parties/${partyId}/job_skills`, {
|
return this.request<Party>(`/parties/${partyId}/job_skills`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
body: {
|
body: {
|
||||||
slot: skillSlot
|
party: {
|
||||||
|
skill_position: skillSlot
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
} from '$lib/utils/jobUtils'
|
} from '$lib/utils/jobUtils'
|
||||||
import { getAccessoryImage, getBasePath } from '$lib/utils/images'
|
import { getAccessoryImage, getBasePath } from '$lib/utils/images'
|
||||||
import Icon from '$lib/components/Icon.svelte'
|
import Icon from '$lib/components/Icon.svelte'
|
||||||
|
import Button from '$lib/components/ui/Button.svelte'
|
||||||
|
import * as m from '$lib/paraglide/messages'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
job?: Job | undefined
|
job?: Job | undefined
|
||||||
|
|
@ -62,13 +64,8 @@
|
||||||
{#if job}
|
{#if job}
|
||||||
<img class="job-portrait" src={jobImageUrl} alt={job.name.en} />
|
<img class="job-portrait" src={jobImageUrl} alt={job.name.en} />
|
||||||
<div class="overlay"></div>
|
<div class="overlay"></div>
|
||||||
{:else if canEdit}
|
{:else}
|
||||||
<div class="empty-portrait">
|
<div class="empty-portrait"></div>
|
||||||
<button class="select-job-button" on:click={onSelectJob}>
|
|
||||||
<Icon name="plus" size={24} />
|
|
||||||
<span>Select Job</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if canEdit && job}
|
{#if canEdit && job}
|
||||||
|
|
@ -167,7 +164,11 @@
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="no-job-message" class:readonly={!canEdit}>
|
<div class="no-job-message" class:readonly={!canEdit}>
|
||||||
<p>{canEdit ? 'Select a job to view skills and details' : 'No job selected'}</p>
|
{#if canEdit}
|
||||||
|
<Button onclick={onSelectJob} small>{m.job_choose()}</Button>
|
||||||
|
{:else}
|
||||||
|
<p>No job selected</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -240,34 +241,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-portrait {
|
.empty-portrait {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: var(--text-secondary);
|
|
||||||
font-size: typography.$font-regular;
|
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-job-button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: spacing.$unit-half;
|
|
||||||
padding: spacing.$unit spacing.$unit-2x;
|
|
||||||
background: var(--button-primary-bg);
|
|
||||||
color: var(--button-primary-text);
|
|
||||||
border: none;
|
|
||||||
border-radius: layout.$card-corner;
|
|
||||||
font-size: typography.$font-regular;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--button-primary-bg-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.change-job-button {
|
.change-job-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: spacing.$unit;
|
top: spacing.$unit;
|
||||||
|
|
|
||||||
|
|
@ -63,12 +63,12 @@
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
icon="close"
|
icon="close"
|
||||||
on:click={handleRemove}
|
onclick={handleRemove}
|
||||||
aria-label="Remove skill"
|
aria-label="Remove skill"
|
||||||
type="button"
|
type="button"
|
||||||
class="remove-button"
|
class="remove-button"
|
||||||
iconOnly
|
iconOnly
|
||||||
></Button>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,13 @@
|
||||||
useUnfavoriteParty
|
useUnfavoriteParty
|
||||||
} from '$lib/api/mutations/party.mutations'
|
} from '$lib/api/mutations/party.mutations'
|
||||||
|
|
||||||
|
// TanStack Query mutations - Job
|
||||||
|
import {
|
||||||
|
useUpdatePartyJob,
|
||||||
|
useUpdatePartyJobSkills,
|
||||||
|
useRemovePartyJobSkill
|
||||||
|
} from '$lib/api/mutations/job.mutations'
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
import { getLocalId } from '$lib/utils/localId'
|
import { getLocalId } from '$lib/utils/localId'
|
||||||
import { getEditKey, storeEditKey, computeEditability } from '$lib/utils/editKeys'
|
import { getEditKey, storeEditKey, computeEditability } from '$lib/utils/editKeys'
|
||||||
|
|
@ -152,6 +159,11 @@
|
||||||
const favoritePartyMutation = useFavoriteParty()
|
const favoritePartyMutation = useFavoriteParty()
|
||||||
const unfavoritePartyMutation = useUnfavoriteParty()
|
const unfavoritePartyMutation = useUnfavoriteParty()
|
||||||
|
|
||||||
|
// TanStack Query mutations - Job
|
||||||
|
const updateJobMutation = useUpdatePartyJob()
|
||||||
|
const updateJobSkillsMutation = useUpdatePartyJobSkills()
|
||||||
|
const removeJobSkillMutation = useRemovePartyJobSkill()
|
||||||
|
|
||||||
// Create drag-drop context
|
// Create drag-drop context
|
||||||
const dragContext = createDragDropContext({
|
const dragContext = createDragDropContext({
|
||||||
onLocalUpdate: async (operation) => {
|
onLocalUpdate: async (operation) => {
|
||||||
|
|
@ -498,9 +510,11 @@
|
||||||
error = null
|
error = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Update job via API (use shortcode for party identification)
|
// Use mutation for proper cache invalidation
|
||||||
await partyAdapter.updateJob(party.shortcode, job.id)
|
await updateJobMutation.mutateAsync({
|
||||||
// Party will be updated via cache invalidation
|
shortcode: party.shortcode,
|
||||||
|
jobId: job.id
|
||||||
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e instanceof Error ? e.message : 'Failed to update job'
|
error = e instanceof Error ? e.message : 'Failed to update job'
|
||||||
console.error('Failed to update job:', e)
|
console.error('Failed to update job:', e)
|
||||||
|
|
@ -528,18 +542,14 @@
|
||||||
const updatedSkills = { ...party.jobSkills }
|
const updatedSkills = { ...party.jobSkills }
|
||||||
updatedSkills[String(slot) as keyof typeof updatedSkills] = skill
|
updatedSkills[String(slot) as keyof typeof updatedSkills] = skill
|
||||||
|
|
||||||
console.log('[Party] Current jobSkills:', party.jobSkills)
|
|
||||||
console.log('[Party] Updated jobSkills object:', updatedSkills)
|
|
||||||
console.log('[Party] Slot being updated:', slot)
|
|
||||||
console.log('[Party] New skill:', skill)
|
|
||||||
|
|
||||||
// Convert skills object to array format expected by API
|
// Convert skills object to array format expected by API
|
||||||
const skillsArray = transformSkillsToArray(updatedSkills)
|
const skillsArray = transformSkillsToArray(updatedSkills)
|
||||||
|
|
||||||
console.log('[Party] Skills array to send:', skillsArray)
|
// Use mutation for proper cache invalidation
|
||||||
|
await updateJobSkillsMutation.mutateAsync({
|
||||||
await partyAdapter.updateJobSkills(party.shortcode, skillsArray)
|
shortcode: party.shortcode,
|
||||||
// Party will be updated via cache invalidation
|
skills: skillsArray
|
||||||
|
})
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error = extractErrorMessage(e, 'Failed to update skill')
|
error = extractErrorMessage(e, 'Failed to update skill')
|
||||||
console.error('Failed to update skill:', e)
|
console.error('Failed to update skill:', e)
|
||||||
|
|
@ -552,21 +562,11 @@
|
||||||
error = null
|
error = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Remove skill from slot
|
// Use remove mutation for proper cache invalidation
|
||||||
const updatedSkills = { ...party.jobSkills }
|
await removeJobSkillMutation.mutateAsync({
|
||||||
delete updatedSkills[String(slot) as keyof typeof updatedSkills]
|
shortcode: party.shortcode,
|
||||||
|
slot
|
||||||
console.log('[Party] Removing skill from slot:', slot)
|
})
|
||||||
console.log('[Party] Current jobSkills:', party.jobSkills)
|
|
||||||
console.log('[Party] Updated jobSkills after removal:', updatedSkills)
|
|
||||||
|
|
||||||
// Convert skills object to array format expected by API
|
|
||||||
const skillsArray = transformSkillsToArray(updatedSkills)
|
|
||||||
|
|
||||||
console.log('[Party] Skills array to send after removal:', skillsArray)
|
|
||||||
|
|
||||||
await partyAdapter.updateJobSkills(party.shortcode, skillsArray)
|
|
||||||
// Party will be updated via cache invalidation
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error = extractErrorMessage(e, 'Failed to remove skill')
|
error = extractErrorMessage(e, 'Failed to remove skill')
|
||||||
console.error('Failed to remove skill:', e)
|
console.error('Failed to remove skill:', e)
|
||||||
|
|
@ -585,15 +585,11 @@
|
||||||
error = null
|
error = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Remove skill from slot
|
// Use remove mutation for proper cache invalidation
|
||||||
const updatedSkills = { ...party.jobSkills }
|
await removeJobSkillMutation.mutateAsync({
|
||||||
delete updatedSkills[String(slot) as keyof typeof updatedSkills]
|
shortcode: party.shortcode,
|
||||||
|
slot
|
||||||
// Convert skills object to array format expected by API
|
})
|
||||||
const skillsArray = transformSkillsToArray(updatedSkills)
|
|
||||||
|
|
||||||
await partyAdapter.updateJobSkills(party.shortcode, skillsArray)
|
|
||||||
// Party will be updated via cache invalidation
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e instanceof Error ? e.message : 'Failed to remove skill'
|
error = e instanceof Error ? e.message : 'Failed to remove skill'
|
||||||
console.error('Failed to remove skill:', e)
|
console.error('Failed to remove skill:', e)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue