diff --git a/src/lib/composables/drag-drop.svelte.ts b/src/lib/composables/drag-drop.svelte.ts
index 10ec8b62..7613ca55 100644
--- a/src/lib/composables/drag-drop.svelte.ts
+++ b/src/lib/composables/drag-drop.svelte.ts
@@ -30,11 +30,13 @@ export interface DragOperation {
container: string
position: number
itemId: string
+ type?: GridItemType
}
target: {
container: string
position: number
itemId?: string
+ type?: GridItemType
}
status: 'pending' | 'synced' | 'failed'
retryCount: number
@@ -192,7 +194,7 @@ export function createDragDropContext(handlers: DragDropHandlers = {}) {
return 'move'
}
- function endDrag(targetHasItem: boolean = false) {
+ function endDrag(targetItem?: GridItem) {
try {
console.group('π Drag End')
console.log('Final state:', { ...state })
@@ -200,17 +202,19 @@ export function createDragDropContext(handlers: DragDropHandlers = {}) {
if (state.validDrop && state.draggedItem && state.hoveredOver) {
const operation: DragOperation = {
id: crypto.randomUUID(),
- type: determineOperationType(state.draggedItem.source, state.hoveredOver, targetHasItem),
+ type: determineOperationType(state.draggedItem.source, state.hoveredOver, !!targetItem),
timestamp: Date.now(),
source: {
container: state.draggedItem.source.container,
position: state.draggedItem.source.position,
- itemId: state.draggedItem.data.id
+ itemId: state.draggedItem.data.id,
+ type: state.draggedItem.source.type
},
target: {
container: state.hoveredOver.container,
position: state.hoveredOver.position,
- itemId: targetHasItem ? 'has-item' : undefined
+ itemId: targetItem?.id || undefined,
+ type: state.hoveredOver.type
},
status: 'pending',
retryCount: 0
@@ -316,7 +320,7 @@ export function createDragDropContext(handlers: DragDropHandlers = {}) {
}
console.groupEnd()
- endDrag(!!targetItem)
+ endDrag(targetItem)
return true
}
diff --git a/src/routes/api/parties/[id]/grid_characters/+server.ts b/src/routes/api/parties/[id]/grid_characters/+server.ts
new file mode 100644
index 00000000..57669375
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_characters/+server.ts
@@ -0,0 +1,39 @@
+import { json, type RequestHandler } from '@sveltejs/kit'
+import { buildUrl } from '$lib/api/core'
+
+/**
+ * POST /api/parties/[id]/grid_characters - Add character to party
+ * Proxies to Rails API with proper authentication
+ */
+
+export const POST: RequestHandler = async ({ request, params, fetch, cookies }) => {
+ try {
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward to Rails API
+ const response = await fetch(buildUrl('/characters'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify({
+ character: {
+ party_id: params.id,
+ ...body
+ }
+ })
+ })
+
+ const data = await response.json()
+ return json(data, { status: response.status })
+ } catch (error) {
+ console.error('Error adding character:', error)
+ return json(
+ { error: 'Failed to add character' },
+ { status: 500 }
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/routes/api/parties/[id]/grid_characters/[characterId]/position/+server.ts b/src/routes/api/parties/[id]/grid_characters/[characterId]/position/+server.ts
new file mode 100644
index 00000000..2a4c7edf
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_characters/[characterId]/position/+server.ts
@@ -0,0 +1,31 @@
+import { json } from '@sveltejs/kit'
+import type { RequestHandler } from './$types'
+import { buildUrl } from '$lib/api/core'
+
+export const PUT: RequestHandler = async ({ params, request, fetch, cookies }) => {
+ const { id: partyId, characterId } = params
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward the request to the Rails API
+ const apiResponse = await fetch(
+ buildUrl(`/parties/${partyId}/grid_characters/${characterId}/position`),
+ {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify(body)
+ }
+ )
+
+ if (!apiResponse.ok) {
+ const error = await apiResponse.json().catch(() => ({ error: 'Failed to update character position' }))
+ return json(error, { status: apiResponse.status })
+ }
+
+ const data = await apiResponse.json()
+ return json(data)
+}
\ No newline at end of file
diff --git a/src/routes/api/parties/[id]/grid_characters/swap/+server.ts b/src/routes/api/parties/[id]/grid_characters/swap/+server.ts
new file mode 100644
index 00000000..5f2867fe
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_characters/swap/+server.ts
@@ -0,0 +1,31 @@
+import { json } from '@sveltejs/kit'
+import type { RequestHandler } from './$types'
+import { buildUrl } from '$lib/api/core'
+
+export const POST: RequestHandler = async ({ params, request, fetch, cookies }) => {
+ const { id: partyId } = params
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward the request to the Rails API
+ const apiResponse = await fetch(
+ buildUrl(`/parties/${partyId}/grid_characters/swap`),
+ {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify(body)
+ }
+ )
+
+ if (!apiResponse.ok) {
+ const error = await apiResponse.json().catch(() => ({ error: 'Failed to swap characters' }))
+ return json(error, { status: apiResponse.status })
+ }
+
+ const data = await apiResponse.json()
+ return json(data)
+}
\ No newline at end of file
diff --git a/src/routes/api/parties/[id]/grid_summons/+server.ts b/src/routes/api/parties/[id]/grid_summons/+server.ts
new file mode 100644
index 00000000..85abd0c8
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_summons/+server.ts
@@ -0,0 +1,39 @@
+import { json, type RequestHandler } from '@sveltejs/kit'
+import { buildUrl } from '$lib/api/core'
+
+/**
+ * POST /api/parties/[id]/grid_summons - Add summon to party
+ * Proxies to Rails API with proper authentication
+ */
+
+export const POST: RequestHandler = async ({ request, params, fetch, cookies }) => {
+ try {
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward to Rails API
+ const response = await fetch(buildUrl('/summons'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify({
+ summon: {
+ party_id: params.id,
+ ...body
+ }
+ })
+ })
+
+ const data = await response.json()
+ return json(data, { status: response.status })
+ } catch (error) {
+ console.error('Error adding summon:', error)
+ return json(
+ { error: 'Failed to add summon' },
+ { status: 500 }
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/routes/api/parties/[id]/grid_summons/[summonId]/position/+server.ts b/src/routes/api/parties/[id]/grid_summons/[summonId]/position/+server.ts
new file mode 100644
index 00000000..9f9d7856
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_summons/[summonId]/position/+server.ts
@@ -0,0 +1,31 @@
+import { json } from '@sveltejs/kit'
+import type { RequestHandler } from './$types'
+import { buildUrl } from '$lib/api/core'
+
+export const PUT: RequestHandler = async ({ params, request, fetch, cookies }) => {
+ const { id: partyId, summonId } = params
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward the request to the Rails API
+ const apiResponse = await fetch(
+ buildUrl(`/parties/${partyId}/grid_summons/${summonId}/position`),
+ {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify(body)
+ }
+ )
+
+ if (!apiResponse.ok) {
+ const error = await apiResponse.json().catch(() => ({ error: 'Failed to update summon position' }))
+ return json(error, { status: apiResponse.status })
+ }
+
+ const data = await apiResponse.json()
+ return json(data)
+}
\ No newline at end of file
diff --git a/src/routes/api/parties/[id]/grid_summons/swap/+server.ts b/src/routes/api/parties/[id]/grid_summons/swap/+server.ts
new file mode 100644
index 00000000..3d8576ec
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_summons/swap/+server.ts
@@ -0,0 +1,31 @@
+import { json } from '@sveltejs/kit'
+import type { RequestHandler } from './$types'
+import { buildUrl } from '$lib/api/core'
+
+export const POST: RequestHandler = async ({ params, request, fetch, cookies }) => {
+ const { id: partyId } = params
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward the request to the Rails API
+ const apiResponse = await fetch(
+ buildUrl(`/parties/${partyId}/grid_summons/swap`),
+ {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify(body)
+ }
+ )
+
+ if (!apiResponse.ok) {
+ const error = await apiResponse.json().catch(() => ({ error: 'Failed to swap summons' }))
+ return json(error, { status: apiResponse.status })
+ }
+
+ const data = await apiResponse.json()
+ return json(data)
+}
\ No newline at end of file
diff --git a/src/routes/api/parties/[id]/grid_weapons/+server.ts b/src/routes/api/parties/[id]/grid_weapons/+server.ts
new file mode 100644
index 00000000..829204a0
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_weapons/+server.ts
@@ -0,0 +1,39 @@
+import { json, type RequestHandler } from '@sveltejs/kit'
+import { buildUrl } from '$lib/api/core'
+
+/**
+ * POST /api/parties/[id]/grid_weapons - Add weapon to party
+ * Proxies to Rails API with proper authentication
+ */
+
+export const POST: RequestHandler = async ({ request, params, fetch, cookies }) => {
+ try {
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward to Rails API
+ const response = await fetch(buildUrl('/weapons'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify({
+ weapon: {
+ party_id: params.id,
+ ...body
+ }
+ })
+ })
+
+ const data = await response.json()
+ return json(data, { status: response.status })
+ } catch (error) {
+ console.error('Error adding weapon:', error)
+ return json(
+ { error: 'Failed to add weapon' },
+ { status: 500 }
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/routes/api/parties/[id]/grid_weapons/[weaponId]/position/+server.ts b/src/routes/api/parties/[id]/grid_weapons/[weaponId]/position/+server.ts
new file mode 100644
index 00000000..793f1338
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_weapons/[weaponId]/position/+server.ts
@@ -0,0 +1,31 @@
+import { json } from '@sveltejs/kit'
+import type { RequestHandler } from './$types'
+import { buildUrl } from '$lib/api/core'
+
+export const PUT: RequestHandler = async ({ params, request, fetch, cookies }) => {
+ const { id: partyId, weaponId } = params
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward the request to the Rails API
+ const apiResponse = await fetch(
+ buildUrl(`/parties/${partyId}/grid_weapons/${weaponId}/position`),
+ {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify(body)
+ }
+ )
+
+ if (!apiResponse.ok) {
+ const error = await apiResponse.json().catch(() => ({ error: 'Failed to update weapon position' }))
+ return json(error, { status: apiResponse.status })
+ }
+
+ const data = await apiResponse.json()
+ return json(data)
+}
\ No newline at end of file
diff --git a/src/routes/api/parties/[id]/grid_weapons/swap/+server.ts b/src/routes/api/parties/[id]/grid_weapons/swap/+server.ts
new file mode 100644
index 00000000..be32c641
--- /dev/null
+++ b/src/routes/api/parties/[id]/grid_weapons/swap/+server.ts
@@ -0,0 +1,31 @@
+import { json } from '@sveltejs/kit'
+import type { RequestHandler } from './$types'
+import { buildUrl } from '$lib/api/core'
+
+export const POST: RequestHandler = async ({ params, request, fetch, cookies }) => {
+ const { id: partyId } = params
+ const body = await request.json()
+ const editKey = request.headers.get('X-Edit-Key')
+
+ // Forward the request to the Rails API
+ const apiResponse = await fetch(
+ buildUrl(`/parties/${partyId}/grid_weapons/swap`),
+ {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${cookies.get('access_token')}`,
+ ...(editKey ? { 'X-Edit-Key': editKey } : {})
+ },
+ body: JSON.stringify(body)
+ }
+ )
+
+ if (!apiResponse.ok) {
+ const error = await apiResponse.json().catch(() => ({ error: 'Failed to swap weapons' }))
+ return json(error, { status: apiResponse.status })
+ }
+
+ const data = await apiResponse.json()
+ return json(data)
+}
\ No newline at end of file
diff --git a/src/routes/test/drag-drop/+page.svelte b/src/routes/test/drag-drop/+page.svelte
new file mode 100644
index 00000000..74734c9b
--- /dev/null
+++ b/src/routes/test/drag-drop/+page.svelte
@@ -0,0 +1,688 @@
+
{JSON.stringify(operations, null, 2)}
+