teams/new: reformat and restructure page

This commit is contained in:
Justin Edmund 2025-12-13 14:35:03 -08:00
parent 47563634b3
commit 015650104e

View file

@ -6,8 +6,14 @@
import SummonGrid from '$lib/components/grids/SummonGrid.svelte' import SummonGrid from '$lib/components/grids/SummonGrid.svelte'
import CharacterGrid from '$lib/components/grids/CharacterGrid.svelte' import CharacterGrid from '$lib/components/grids/CharacterGrid.svelte'
import JobSection from '$lib/components/job/JobSection.svelte' import JobSection from '$lib/components/job/JobSection.svelte'
import { openSearchSidebar, closeSearchSidebar } from '$lib/features/search/openSearchSidebar.svelte' import {
import { openJobSelectionSidebar, openJobSkillSelectionSidebar } from '$lib/features/job/openJobSidebar.svelte' openSearchSidebar,
closeSearchSidebar
} from '$lib/features/search/openSearchSidebar.svelte'
import {
openJobSelectionSidebar,
openJobSkillSelectionSidebar
} from '$lib/features/job/openJobSidebar.svelte'
import PartySegmentedControl from '$lib/components/party/PartySegmentedControl.svelte' import PartySegmentedControl from '$lib/components/party/PartySegmentedControl.svelte'
import { GridType } from '$lib/types/enums' import { GridType } from '$lib/types/enums'
import { Gender } from '$lib/utils/jobUtils' import { Gender } from '$lib/utils/jobUtils'
@ -76,27 +82,31 @@
// Set selectedSlot to first valid empty slot for this tab // Set selectedSlot to first valid empty slot for this tab
if (gridType === GridType.Character) { if (gridType === GridType.Character) {
// Find first empty character slot // Find first empty character slot
const emptySlot = [0, 1, 2, 3, 4].find(i => !characters.find(c => c.position === i)) const emptySlot = [0, 1, 2, 3, 4].find((i) => !characters.find((c) => c.position === i))
selectedSlot = emptySlot ?? 0 selectedSlot = emptySlot ?? 0
} else if (gridType === GridType.Weapon) { } else if (gridType === GridType.Weapon) {
// Find first empty weapon slot (mainhand first, then grid) // Find first empty weapon slot (mainhand first, then grid)
const emptySlot = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8].find(i => const emptySlot = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8].find(
!weapons.find(w => w.position === i || (i === -1 && w.mainhand)) (i) => !weapons.find((w) => w.position === i || (i === -1 && w.mainhand))
) )
selectedSlot = emptySlot ?? -1 selectedSlot = emptySlot ?? -1
} else { } else {
// Find first empty summon slot (main, grid, friend) // Find first empty summon slot (main, grid, friend)
const emptySlot = [-1, 0, 1, 2, 3, 6].find(i => const emptySlot = [-1, 0, 1, 2, 3, 6].find(
!summons.find(s => s.position === i || (i === -1 && s.main) || (i === 6 && s.friend)) (i) =>
!summons.find((s) => s.position === i || (i === -1 && s.main) || (i === 6 && s.friend))
) )
selectedSlot = emptySlot ?? -1 selectedSlot = emptySlot ?? -1
} }
// Open sidebar when switching tabs // Open sidebar when switching tabs
openSearchSidebar({ openSearchSidebar({
type: gridType === GridType.Weapon ? 'weapon' : type:
gridType === GridType.Summon ? 'summon' : gridType === GridType.Weapon
'character', ? 'weapon'
: gridType === GridType.Summon
? 'summon'
: 'character',
onAddItems: handleAddItems, onAddItems: handleAddItems,
canAddMore: !isGridFull(gridType) canAddMore: !isGridFull(gridType)
}) })
@ -269,9 +279,11 @@
let isCharacterGridFull = $derived(characters.length >= 5) // 5 character slots let isCharacterGridFull = $derived(characters.length >= 5) // 5 character slots
let canAddMore = $derived( let canAddMore = $derived(
activeTab === GridType.Weapon ? !isWeaponGridFull : activeTab === GridType.Weapon
activeTab === GridType.Summon ? !isSummonGridFull : ? !isWeaponGridFull
!isCharacterGridFull : activeTab === GridType.Summon
? !isSummonGridFull
: !isCharacterGridFull
) )
// Handle adding items from search // Handle adding items from search
@ -323,16 +335,18 @@
} }
// Update the query cache with the created party // Update the query cache with the created party
queryClient.setQueryData( queryClient.setQueryData(partyKeys.detail(createdParty.shortcode), createdParty)
partyKeys.detail(createdParty.shortcode),
createdParty
)
// Step 2: Add the first item to the party // Step 2: Add the first item to the party
let position = selectedSlot !== null ? selectedSlot : -1 // Use selectedSlot if available let position = selectedSlot !== null ? selectedSlot : -1 // Use selectedSlot if available
let itemAdded = false let itemAdded = false
try { try {
console.log('Adding item to party:', { partyId, itemId: firstItem.id, type: activeTab, position }) console.log('Adding item to party:', {
partyId,
itemId: firstItem.id,
type: activeTab,
position
})
if (activeTab === GridType.Weapon) { if (activeTab === GridType.Weapon) {
// Use selectedSlot if available, otherwise default to mainhand // Use selectedSlot if available, otherwise default to mainhand
@ -422,7 +436,8 @@
} else if (error.errors && typeof error.errors === 'object') { } else if (error.errors && typeof error.errors === 'object') {
// Rails-style validation errors // Rails-style validation errors
errorDetails = Object.entries(error.errors).map( errorDetails = Object.entries(error.errors).map(
([field, messages]) => `${field}: ${Array.isArray(messages) ? messages.join(', ') : messages}` ([field, messages]) =>
`${field}: ${Array.isArray(messages) ? messages.join(', ') : messages}`
) )
} else { } else {
errorDetails = [] errorDetails = []
@ -443,13 +458,18 @@
if (activeTab === GridType.Weapon) { if (activeTab === GridType.Weapon) {
// Use selectedSlot for first item if available // Use selectedSlot for first item if available
if (i === 0 && selectedSlot !== null && !weapons.find(w => w.position === selectedSlot)) { if (
i === 0 &&
selectedSlot !== null &&
!weapons.find((w) => w.position === selectedSlot)
) {
position = selectedSlot position = selectedSlot
selectedSlot = null // Reset after using selectedSlot = null // Reset after using
} else { } else {
// Find next empty weapon slot // Find next empty weapon slot
const emptySlots = Array.from({ length: 10 }, (_, i) => i - 1) const emptySlots = Array.from({ length: 10 }, (_, i) => i - 1).filter(
.filter(i => !weapons.find(w => w.position === i)) (i) => !weapons.find((w) => w.position === i)
)
if (emptySlots.length === 0) return // Grid full if (emptySlots.length === 0) return // Grid full
position = emptySlots[0]! position = emptySlots[0]!
} }
@ -466,13 +486,17 @@
addItemToCache('weapons', response) addItemToCache('weapons', response)
} else if (activeTab === GridType.Summon) { } else if (activeTab === GridType.Summon) {
// Use selectedSlot for first item if available // Use selectedSlot for first item if available
if (i === 0 && selectedSlot !== null && !summons.find(s => s.position === selectedSlot)) { if (
i === 0 &&
selectedSlot !== null &&
!summons.find((s) => s.position === selectedSlot)
) {
position = selectedSlot position = selectedSlot
selectedSlot = null // Reset after using selectedSlot = null // Reset after using
} else { } else {
// Find next empty summon slot // Find next empty summon slot
const emptySlots = [-1, 0, 1, 2, 3, 6] // main, 4 grid slots, friend const emptySlots = [-1, 0, 1, 2, 3, 6] // main, 4 grid slots, friend
.filter(i => !summons.find(s => s.position === i)) .filter((i) => !summons.find((s) => s.position === i))
if (emptySlots.length === 0) return // Grid full if (emptySlots.length === 0) return // Grid full
position = emptySlots[0]! position = emptySlots[0]!
} }
@ -490,13 +514,18 @@
addItemToCache('summons', response) addItemToCache('summons', response)
} else if (activeTab === GridType.Character) { } else if (activeTab === GridType.Character) {
// Use selectedSlot for first item if available // Use selectedSlot for first item if available
if (i === 0 && selectedSlot !== null && !characters.find(c => c.position === selectedSlot)) { if (
i === 0 &&
selectedSlot !== null &&
!characters.find((c) => c.position === selectedSlot)
) {
position = selectedSlot position = selectedSlot
selectedSlot = null // Reset after using selectedSlot = null // Reset after using
} else { } else {
// Find next empty character slot // Find next empty character slot
const emptySlots = Array.from({ length: 5 }, (_, i) => i) const emptySlots = Array.from({ length: 5 }, (_, i) => i).filter(
.filter(i => !characters.find(c => c.position === i)) (i) => !characters.find((c) => c.position === i)
)
if (emptySlots.length === 0) return // Grid full if (emptySlots.length === 0) return // Grid full
position = emptySlots[0]! position = emptySlots[0]!
} }
@ -522,7 +551,6 @@
} }
} }
// Provide party context using query data // Provide party context using query data
setContext('party', { setContext('party', {
getParty: () => party, getParty: () => party,
@ -565,15 +593,21 @@
} }
} }
}, },
openPicker: (opts: { type: 'weapon' | 'summon' | 'character'; position: number; item?: any }) => { openPicker: (opts: {
type: 'weapon' | 'summon' | 'character'
position: number
item?: any
}) => {
selectedSlot = opts.position selectedSlot = opts.position
openSearchSidebar({ openSearchSidebar({
type: opts.type, type: opts.type,
onAddItems: handleAddItems, onAddItems: handleAddItems,
canAddMore: !isGridFull( canAddMore: !isGridFull(
opts.type === 'weapon' ? GridType.Weapon : opts.type === 'weapon'
opts.type === 'summon' ? GridType.Summon : ? GridType.Weapon
GridType.Character : opts.type === 'summon'
? GridType.Summon
: GridType.Character
) )
}) })
} }
@ -625,11 +659,7 @@
console.log('Open accessory selection sidebar') console.log('Open accessory selection sidebar')
}} }}
/> />
<CharacterGrid <CharacterGrid {characters} {mainWeaponElement} {partyElement} />
{characters}
{mainWeaponElement}
{partyElement}
/>
</div> </div>
{/if} {/if}
</div> </div>
@ -659,9 +689,7 @@
{/if} {/if}
<div class="dialog-actions"> <div class="dialog-actions">
<Dialog.Close class="dialog-button"> <Dialog.Close class="dialog-button">OK</Dialog.Close>
OK
</Dialog.Close>
</div> </div>
</Dialog.Content> </Dialog.Content>
</Dialog.Portal> </Dialog.Portal>
@ -719,7 +747,7 @@
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
z-index: 50; z-index: 50;
} }
/*
:global(.dialog-content) { :global(.dialog-content) {
position: fixed; position: fixed;
left: 50%; left: 50%;
@ -734,7 +762,7 @@
overflow-y: auto; overflow-y: auto;
z-index: 51; z-index: 51;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2); box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
} } */
.dialog-title { .dialog-title {
font-size: 18px; font-size: 18px;