From 5919548bc1c44f67f323dae6493b2e9a0ee0ffc4 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 29 Nov 2025 02:54:58 -0800 Subject: [PATCH] add grid operations utility - getCollectionKey: map grid type to party collection - getGridMethodName: map operation + type to service method - executeGridOperation: consolidate move/swap operations - removeGridItem: generic grid item removal - updateGridItem: generic grid item updates --- src/lib/utils/gridOperations.ts | 207 ++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 src/lib/utils/gridOperations.ts diff --git a/src/lib/utils/gridOperations.ts b/src/lib/utils/gridOperations.ts new file mode 100644 index 00000000..8946e4c9 --- /dev/null +++ b/src/lib/utils/gridOperations.ts @@ -0,0 +1,207 @@ +/** + * Grid operation utilities + * Consolidates duplicated grid CRUD logic + */ + +import type { Party } from '$lib/types/api/party' +import type { GridService } from '$lib/services/grid.service' +import type { PartyService } from '$lib/services/party.service' + +export type GridItemType = 'character' | 'weapon' | 'summon' +export type GridCollection = 'characters' | 'weapons' | 'summons' + +/** + * Maps grid item type to collection key in Party object + * + * @param type - Grid item type (character, weapon, or summon) + * @returns Collection key name + * + * @example + * ```typescript + * const key = getCollectionKey('weapon') // Returns: 'weapons' + * const items = party[key] // Access party.weapons + * ``` + */ +export function getCollectionKey(type: GridItemType): GridCollection { + const map: Record = { + character: 'characters', + weapon: 'weapons', + summon: 'summons' + } + return map[type] +} + +/** + * Maps operation and grid type to service method name + * + * @param operation - CRUD operation type + * @param type - Grid item type + * @returns Method name on GridService + * + * @example + * ```typescript + * const methodName = getGridMethodName('add', 'weapon') // Returns: 'addWeapon' + * const methodName = getGridMethodName('remove', 'character') // Returns: 'removeCharacter' + * ``` + */ +export function getGridMethodName( + operation: 'add' | 'move' | 'remove' | 'update', + type: GridItemType +): string { + const typeCapitalized = type.charAt(0).toUpperCase() + type.slice(1) + return `${operation}${typeCapitalized}` +} + +/** + * Execute grid move/swap operation + * Consolidates handleSwap and handleMove logic + * + * @param operationType - Type of operation (move or swap) + * @param source - Source item information + * @param target - Target position information + * @param context - Party context (ID, shortcode, edit key) + * @param gridService - Grid service instance + * @param partyService - Party service instance + * @returns Updated party data + * + * @example + * ```typescript + * const updated = await executeGridOperation( + * 'swap', + * { type: 'weapon', itemId: 'abc123', position: 0 }, + * { type: 'weapon', position: 1, itemId: 'def456' }, + * { partyId: party.id, shortcode: party.shortcode, editKey }, + * gridService, + * partyService + * ) + * ``` + */ +export async function executeGridOperation( + operationType: 'move' | 'swap', + source: { type: GridItemType; itemId: string; position: number }, + target: { type: GridItemType; position: number; itemId?: string }, + context: { partyId: string; shortcode: string; editKey?: string }, + gridService: GridService, + partyService: PartyService +): Promise { + // Validation + if (operationType === 'swap' && !target.itemId) { + throw new Error('Swap operation requires target item') + } + if (operationType === 'move' && target.itemId) { + throw new Error('Move operation requires empty target') + } + + // Call appropriate grid service method + const methodName = getGridMethodName('move', source.type) + const method = (gridService as any)[methodName] + + if (!method) { + throw new Error(`Unknown grid method: ${methodName}`) + } + + await method.call( + gridService, + context.partyId, + source.itemId, + target.position, + context.editKey, + { shortcode: context.shortcode } + ) + + // Clear cache and refresh party + partyService.clearPartyCache(context.shortcode) + return await partyService.getByShortcode(context.shortcode) +} + +/** + * Generic grid item remover + * Replaces three similar remove{Type} methods in clientGridService + * + * @param type - Grid item type to remove + * @param partyId - Party UUID + * @param gridItemId - Grid item UUID to remove + * @param party - Current party state + * @param shortcode - Party shortcode for cache clearing + * @param editKey - Optional edit key for authorization + * @param gridService - Grid service instance + * @returns Updated party with item removed + * + * @example + * ```typescript + * const updated = await removeGridItem( + * 'weapon', + * party.id, + * gridWeaponId, + * party, + * party.shortcode, + * editKey, + * gridService + * ) + * ``` + */ +export async function removeGridItem( + type: GridItemType, + partyId: string, + gridItemId: string, + party: Party, + shortcode: string, + editKey: string | undefined, + gridService: GridService +): Promise { + // Call appropriate remove method + const methodName = getGridMethodName('remove', type) + const method = (gridService as any)[methodName] + + await method.call(gridService, partyId, gridItemId, editKey, { shortcode }) + + // Update local state by removing item + const collection = getCollectionKey(type) + const updatedParty = { ...party } + + if (updatedParty[collection]) { + updatedParty[collection] = updatedParty[collection].filter( + (item: any) => item.id !== gridItemId + ) + } + + return updatedParty +} + +/** + * Generic grid item updater + * Replaces three similar update{Type} methods + * + * @param type - Grid item type to update + * @param partyId - Party UUID + * @param gridItemId - Grid item UUID to update + * @param updates - Object containing fields to update + * @param editKey - Optional edit key for authorization + * @param gridService - Grid service instance + * @returns Updated grid item data + * + * @example + * ```typescript + * const updated = await updateGridItem( + * 'weapon', + * party.id, + * gridWeaponId, + * { ax1: 10, ax2: 5 }, + * editKey, + * gridService + * ) + * ``` + */ +export async function updateGridItem( + type: GridItemType, + partyId: string, + gridItemId: string, + updates: any, + editKey: string | undefined, + gridService: GridService +): Promise { + const methodName = getGridMethodName('update', type) + const method = (gridService as any)[methodName] + + return await method.call(gridService, partyId, gridItemId, updates, editKey) +}