feat: Create UserAdapter and complete Phase 1 & 2 of migration
- Created new UserAdapter for user profile and favorites operations - Updated routes/teams/explore and routes/[username] to use adapters directly - Deleted resource facade files (parties.ts, grid.ts, users.ts) - All services and initial routes now use adapters without backward compatibility - Updated migration plan to track completed work
This commit is contained in:
parent
2605a539b6
commit
683c28e172
7 changed files with 164 additions and 504 deletions
|
|
@ -51,5 +51,12 @@ export type {
|
||||||
Summon
|
Summon
|
||||||
} from './entity.adapter'
|
} from './entity.adapter'
|
||||||
|
|
||||||
|
export { UserAdapter, userAdapter } from './user.adapter'
|
||||||
|
export type {
|
||||||
|
UserInfo,
|
||||||
|
UserProfile,
|
||||||
|
UserProfileResponse
|
||||||
|
} from './user.adapter'
|
||||||
|
|
||||||
// Reactive resources using Svelte 5 runes
|
// Reactive resources using Svelte 5 runes
|
||||||
export * from './resources'
|
export * from './resources'
|
||||||
131
src/lib/api/adapters/user.adapter.ts
Normal file
131
src/lib/api/adapters/user.adapter.ts
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
import { BaseAdapter } from './base.adapter'
|
||||||
|
import type { Party } from '$lib/types/api/party'
|
||||||
|
|
||||||
|
export interface UserInfo {
|
||||||
|
id: string
|
||||||
|
username: string
|
||||||
|
language: string
|
||||||
|
private: boolean
|
||||||
|
gender: number
|
||||||
|
theme: string
|
||||||
|
role: number
|
||||||
|
avatar: {
|
||||||
|
picture: string
|
||||||
|
element: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserProfile extends UserInfo {
|
||||||
|
parties?: Party[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserProfileResponse {
|
||||||
|
user: UserProfile
|
||||||
|
items: Party[]
|
||||||
|
page: number
|
||||||
|
total?: number
|
||||||
|
totalPages?: number
|
||||||
|
perPage?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter for user-related API operations
|
||||||
|
*/
|
||||||
|
export class UserAdapter extends BaseAdapter {
|
||||||
|
/**
|
||||||
|
* Get user information
|
||||||
|
*/
|
||||||
|
async getInfo(username: string): Promise<UserInfo> {
|
||||||
|
return this.request<UserInfo>(`/users/info/${encodeURIComponent(username)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user profile with their parties
|
||||||
|
*/
|
||||||
|
async getProfile(username: string, page = 1): Promise<UserProfileResponse> {
|
||||||
|
const params = page > 1 ? { page } : undefined
|
||||||
|
const response = await this.request<{
|
||||||
|
profile: UserProfile
|
||||||
|
meta?: { count?: number; total_pages?: number; per_page?: number }
|
||||||
|
}>(`/users/${encodeURIComponent(username)}`, { params })
|
||||||
|
|
||||||
|
const items = Array.isArray(response.profile?.parties) ? response.profile.parties : []
|
||||||
|
|
||||||
|
return {
|
||||||
|
user: response.profile,
|
||||||
|
items,
|
||||||
|
page,
|
||||||
|
total: response.meta?.count,
|
||||||
|
totalPages: response.meta?.total_pages,
|
||||||
|
perPage: response.meta?.per_page
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user's favorite parties
|
||||||
|
*/
|
||||||
|
async getFavorites(options: { page?: number } = {}): Promise<{
|
||||||
|
items: Party[]
|
||||||
|
page: number
|
||||||
|
total: number
|
||||||
|
totalPages: number
|
||||||
|
perPage: number
|
||||||
|
}> {
|
||||||
|
const { page = 1 } = options
|
||||||
|
const params = page > 1 ? { page } : undefined
|
||||||
|
|
||||||
|
const response = await this.request<{
|
||||||
|
results: Party[]
|
||||||
|
total: number
|
||||||
|
total_pages: number
|
||||||
|
per?: number
|
||||||
|
}>('/parties/favorites', { params })
|
||||||
|
|
||||||
|
return {
|
||||||
|
items: response.results,
|
||||||
|
page,
|
||||||
|
total: response.total,
|
||||||
|
totalPages: response.total_pages,
|
||||||
|
perPage: response.per || 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check username availability
|
||||||
|
*/
|
||||||
|
async checkUsernameAvailability(username: string): Promise<{ available: boolean }> {
|
||||||
|
return this.request<{ available: boolean }>(`/users/check-username`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ username })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check email availability
|
||||||
|
*/
|
||||||
|
async checkEmailAvailability(email: string): Promise<{ available: boolean }> {
|
||||||
|
return this.request<{ available: boolean }>(`/users/check-email`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ email })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update user profile
|
||||||
|
*/
|
||||||
|
async updateProfile(updates: Partial<UserInfo>): Promise<UserInfo> {
|
||||||
|
return this.request<UserInfo>('/users/me', {
|
||||||
|
method: 'PUT',
|
||||||
|
body: JSON.stringify(updates)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current user
|
||||||
|
*/
|
||||||
|
async getCurrentUser(): Promise<UserInfo> {
|
||||||
|
return this.request<UserInfo>('/users/me')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const userAdapter = new UserAdapter()
|
||||||
|
|
@ -1,232 +0,0 @@
|
||||||
/**
|
|
||||||
* Grid API resource functions - Facade layer for migration
|
|
||||||
*
|
|
||||||
* This module provides backward compatibility during the migration
|
|
||||||
* from api/core to the adapter pattern. Services can continue using
|
|
||||||
* these functions while we migrate them incrementally.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { gridAdapter } from '$lib/api/adapters'
|
|
||||||
import type {
|
|
||||||
GridWeapon,
|
|
||||||
GridCharacter,
|
|
||||||
GridSummon
|
|
||||||
} from '$lib/api/adapters'
|
|
||||||
|
|
||||||
// FetchLike type for backward compatibility
|
|
||||||
export type FetchLike = typeof fetch
|
|
||||||
|
|
||||||
// Weapon grid operations
|
|
||||||
export async function addWeapon(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
weaponId: string, // Granblue ID
|
|
||||||
position: number,
|
|
||||||
options?: {
|
|
||||||
mainhand?: boolean
|
|
||||||
uncapLevel?: number
|
|
||||||
transcendenceStep?: number
|
|
||||||
element?: number
|
|
||||||
},
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridWeapon> {
|
|
||||||
return gridAdapter.createWeapon({
|
|
||||||
partyId,
|
|
||||||
weaponId,
|
|
||||||
position,
|
|
||||||
mainhand: position === -1 || options?.mainhand,
|
|
||||||
uncapLevel: options?.uncapLevel ?? 3,
|
|
||||||
transcendenceStage: options?.transcendenceStep ?? 0
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateWeapon(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
gridWeaponId: string,
|
|
||||||
updates: {
|
|
||||||
position?: number
|
|
||||||
uncapLevel?: number
|
|
||||||
transcendenceStep?: number
|
|
||||||
element?: number
|
|
||||||
},
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridWeapon> {
|
|
||||||
return gridAdapter.updateWeapon(gridWeaponId, {
|
|
||||||
position: updates.position,
|
|
||||||
uncapLevel: updates.uncapLevel,
|
|
||||||
transcendenceStage: updates.transcendenceStep,
|
|
||||||
element: updates.element
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeWeapon(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
gridWeaponId: string,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<void> {
|
|
||||||
return gridAdapter.deleteWeapon({
|
|
||||||
id: gridWeaponId,
|
|
||||||
partyId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Summon grid operations
|
|
||||||
export async function addSummon(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
summonId: string, // Granblue ID
|
|
||||||
position: number,
|
|
||||||
options?: {
|
|
||||||
main?: boolean
|
|
||||||
friend?: boolean
|
|
||||||
quickSummon?: boolean
|
|
||||||
uncapLevel?: number
|
|
||||||
transcendenceStep?: number
|
|
||||||
},
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridSummon> {
|
|
||||||
return gridAdapter.createSummon({
|
|
||||||
partyId,
|
|
||||||
summonId,
|
|
||||||
position,
|
|
||||||
main: position === -1 || options?.main,
|
|
||||||
friend: position === 6 || options?.friend,
|
|
||||||
quickSummon: options?.quickSummon ?? false,
|
|
||||||
uncapLevel: options?.uncapLevel ?? 3,
|
|
||||||
transcendenceStage: options?.transcendenceStep ?? 0
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateSummon(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
gridSummonId: string,
|
|
||||||
updates: {
|
|
||||||
position?: number
|
|
||||||
quickSummon?: boolean
|
|
||||||
uncapLevel?: number
|
|
||||||
transcendenceStep?: number
|
|
||||||
},
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridSummon> {
|
|
||||||
return gridAdapter.updateSummon(gridSummonId, {
|
|
||||||
position: updates.position,
|
|
||||||
quickSummon: updates.quickSummon,
|
|
||||||
uncapLevel: updates.uncapLevel,
|
|
||||||
transcendenceStage: updates.transcendenceStep
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeSummon(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
gridSummonId: string,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<void> {
|
|
||||||
return gridAdapter.deleteSummon({
|
|
||||||
id: gridSummonId,
|
|
||||||
partyId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Character grid operations
|
|
||||||
export async function addCharacter(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
characterId: string, // Granblue ID
|
|
||||||
position: number,
|
|
||||||
options?: {
|
|
||||||
uncapLevel?: number
|
|
||||||
transcendenceStep?: number
|
|
||||||
perpetuity?: boolean
|
|
||||||
},
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridCharacter> {
|
|
||||||
return gridAdapter.createCharacter({
|
|
||||||
partyId,
|
|
||||||
characterId,
|
|
||||||
position,
|
|
||||||
uncapLevel: options?.uncapLevel ?? 3,
|
|
||||||
transcendenceStage: options?.transcendenceStep ?? 0
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateCharacter(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
gridCharacterId: string,
|
|
||||||
updates: {
|
|
||||||
position?: number
|
|
||||||
uncapLevel?: number
|
|
||||||
transcendenceStep?: number
|
|
||||||
perpetuity?: boolean
|
|
||||||
},
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridCharacter> {
|
|
||||||
return gridAdapter.updateCharacter(gridCharacterId, {
|
|
||||||
position: updates.position,
|
|
||||||
uncapLevel: updates.uncapLevel,
|
|
||||||
transcendenceStage: updates.transcendenceStep,
|
|
||||||
perpetualModifiers: updates.perpetuity ? {} : undefined
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeCharacter(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
gridCharacterId: string,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<void> {
|
|
||||||
return gridAdapter.deleteCharacter({
|
|
||||||
id: gridCharacterId,
|
|
||||||
partyId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uncap update methods - these use special endpoints
|
|
||||||
export async function updateCharacterUncap(
|
|
||||||
gridCharacterId: string,
|
|
||||||
uncapLevel?: number,
|
|
||||||
transcendenceStep?: number,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridCharacter> {
|
|
||||||
// For uncap updates, we need the partyId which isn't passed here
|
|
||||||
// This is a limitation of the current API design
|
|
||||||
// For now, we'll use the update method with a fake partyId
|
|
||||||
return gridAdapter.updateCharacterUncap({
|
|
||||||
id: gridCharacterId,
|
|
||||||
partyId: 'unknown', // This is a hack - the API should be redesigned
|
|
||||||
uncapLevel: uncapLevel ?? 3,
|
|
||||||
transcendenceStep
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateWeaponUncap(
|
|
||||||
gridWeaponId: string,
|
|
||||||
uncapLevel?: number,
|
|
||||||
transcendenceStep?: number,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridWeapon> {
|
|
||||||
return gridAdapter.updateWeaponUncap({
|
|
||||||
id: gridWeaponId,
|
|
||||||
partyId: 'unknown', // This is a hack - the API should be redesigned
|
|
||||||
uncapLevel: uncapLevel ?? 3,
|
|
||||||
transcendenceStep
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateSummonUncap(
|
|
||||||
gridSummonId: string,
|
|
||||||
uncapLevel?: number,
|
|
||||||
transcendenceStep?: number,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<GridSummon> {
|
|
||||||
return gridAdapter.updateSummonUncap({
|
|
||||||
id: gridSummonId,
|
|
||||||
partyId: 'unknown', // This is a hack - the API should be redesigned
|
|
||||||
uncapLevel: uncapLevel ?? 3,
|
|
||||||
transcendenceStep
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,214 +0,0 @@
|
||||||
/**
|
|
||||||
* Party API resource functions - Facade layer for migration
|
|
||||||
*
|
|
||||||
* This module provides backward compatibility during the migration
|
|
||||||
* from api/core to the adapter pattern. Services can continue using
|
|
||||||
* these functions while we migrate them incrementally.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { partyAdapter } from '$lib/api/adapters'
|
|
||||||
import type { Party } from '$lib/types/api/party'
|
|
||||||
import { z } from 'zod'
|
|
||||||
|
|
||||||
// FetchLike type for backward compatibility
|
|
||||||
export type FetchLike = typeof fetch
|
|
||||||
|
|
||||||
// API functions - Now using PartyAdapter
|
|
||||||
export async function getByShortcode(fetch: FetchLike, shortcode: string): Promise<Party> {
|
|
||||||
// Ignore fetch parameter - adapter handles its own fetching
|
|
||||||
return partyAdapter.getByShortcode(shortcode)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function create(
|
|
||||||
fetch: FetchLike,
|
|
||||||
payload: Partial<Party>,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<{ party: Party; editKey?: string }> {
|
|
||||||
// The adapter returns the party directly, we need to wrap it
|
|
||||||
// to maintain backward compatibility with editKey
|
|
||||||
const party = await partyAdapter.create(payload, headers)
|
|
||||||
|
|
||||||
// Note: editKey is returned in headers by the adapter if present
|
|
||||||
// For now, we'll return just the party
|
|
||||||
return {
|
|
||||||
party,
|
|
||||||
editKey: undefined // Edit key handling may need adjustment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function update(
|
|
||||||
fetch: FetchLike,
|
|
||||||
id: string,
|
|
||||||
payload: Partial<Party>,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<Party> {
|
|
||||||
return partyAdapter.update({ shortcode: id, ...payload }, headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function remix(
|
|
||||||
fetch: FetchLike,
|
|
||||||
shortcode: string,
|
|
||||||
localId?: string,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<{ party: Party; editKey?: string }> {
|
|
||||||
const party = await partyAdapter.remix(shortcode, headers)
|
|
||||||
|
|
||||||
return {
|
|
||||||
party,
|
|
||||||
editKey: undefined // Edit key handling may need adjustment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deleteParty(
|
|
||||||
fetch: FetchLike,
|
|
||||||
id: string,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<void> {
|
|
||||||
return partyAdapter.delete(id, headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List public parties for explore page
|
|
||||||
*/
|
|
||||||
export async function list(
|
|
||||||
fetch: FetchLike,
|
|
||||||
params?: {
|
|
||||||
page?: number
|
|
||||||
per_page?: number
|
|
||||||
raid_id?: string
|
|
||||||
element?: number
|
|
||||||
}
|
|
||||||
): Promise<{
|
|
||||||
items: Party[]
|
|
||||||
total: number
|
|
||||||
totalPages: number
|
|
||||||
perPage: number
|
|
||||||
}> {
|
|
||||||
// Map parameters to adapter format
|
|
||||||
const adapterParams = {
|
|
||||||
page: params?.page,
|
|
||||||
per: params?.per_page,
|
|
||||||
raidId: params?.raid_id,
|
|
||||||
element: params?.element
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await partyAdapter.list(adapterParams)
|
|
||||||
|
|
||||||
// Map adapter response to expected format
|
|
||||||
return {
|
|
||||||
items: response.results,
|
|
||||||
total: response.total,
|
|
||||||
totalPages: response.totalPages,
|
|
||||||
perPage: response.per || 20
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getUserParties(
|
|
||||||
fetch: FetchLike,
|
|
||||||
username: string,
|
|
||||||
filters?: {
|
|
||||||
raid?: string
|
|
||||||
element?: number
|
|
||||||
recency?: number
|
|
||||||
page?: number
|
|
||||||
}
|
|
||||||
): Promise<{
|
|
||||||
parties: Party[]
|
|
||||||
meta?: {
|
|
||||||
count?: number
|
|
||||||
totalPages?: number
|
|
||||||
perPage?: number
|
|
||||||
}
|
|
||||||
}> {
|
|
||||||
// Map parameters to adapter format
|
|
||||||
const adapterParams = {
|
|
||||||
username,
|
|
||||||
page: filters?.page,
|
|
||||||
per: 20, // Default page size
|
|
||||||
visibility: undefined, // Not specified in original
|
|
||||||
raidId: filters?.raid,
|
|
||||||
element: filters?.element,
|
|
||||||
recency: filters?.recency
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await partyAdapter.listUserParties(adapterParams)
|
|
||||||
|
|
||||||
// Map adapter response to expected format
|
|
||||||
return {
|
|
||||||
parties: response.results,
|
|
||||||
meta: {
|
|
||||||
count: response.total,
|
|
||||||
totalPages: response.totalPages,
|
|
||||||
perPage: response.per || 20
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grid operations - These should eventually move to GridAdapter
|
|
||||||
export async function updateWeaponGrid(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
payload: any,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<Party> {
|
|
||||||
// For now, use gridUpdate with a single operation
|
|
||||||
// This is a temporary implementation until GridAdapter is fully integrated
|
|
||||||
const operation = {
|
|
||||||
type: 'add' as const,
|
|
||||||
entity: 'weapon' as const,
|
|
||||||
...payload
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await partyAdapter.gridUpdate(partyId, [operation])
|
|
||||||
|
|
||||||
// Check for conflicts
|
|
||||||
if ('conflicts' in response && response.conflicts) {
|
|
||||||
const error = new Error('Weapon conflict') as any
|
|
||||||
error.conflicts = response
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.party
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateSummonGrid(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
payload: any,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<Party> {
|
|
||||||
// For now, use gridUpdate with a single operation
|
|
||||||
const operation = {
|
|
||||||
type: 'add' as const,
|
|
||||||
entity: 'summon' as const,
|
|
||||||
...payload
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await partyAdapter.gridUpdate(partyId, [operation])
|
|
||||||
return response.party
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateCharacterGrid(
|
|
||||||
fetch: FetchLike,
|
|
||||||
partyId: string,
|
|
||||||
payload: any,
|
|
||||||
headers?: Record<string, string>
|
|
||||||
): Promise<Party> {
|
|
||||||
// For now, use gridUpdate with a single operation
|
|
||||||
const operation = {
|
|
||||||
type: 'add' as const,
|
|
||||||
entity: 'character' as const,
|
|
||||||
...payload
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await partyAdapter.gridUpdate(partyId, [operation])
|
|
||||||
|
|
||||||
// Check for conflicts
|
|
||||||
if ('conflicts' in response && response.conflicts) {
|
|
||||||
const error = new Error('Character conflict') as any
|
|
||||||
error.conflicts = response
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.party
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
import type { FetchLike } from '../core'
|
|
||||||
import { get, buildUrl } from '../core'
|
|
||||||
|
|
||||||
export interface UserInfoResponse {
|
|
||||||
id: string
|
|
||||||
username: string
|
|
||||||
language: string
|
|
||||||
private: boolean
|
|
||||||
gender: number
|
|
||||||
theme: string
|
|
||||||
role: number
|
|
||||||
avatar: {
|
|
||||||
picture: string
|
|
||||||
element: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const users = {
|
|
||||||
info: (f: FetchLike, username: string, init?: RequestInit) =>
|
|
||||||
get<UserInfoResponse>(f, `/users/info/${encodeURIComponent(username)}`, undefined, init)
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserProfileResponse {
|
|
||||||
profile: UserInfoResponse & { parties?: any[] }
|
|
||||||
meta?: { count?: number; total_pages?: number; per_page?: number }
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function profile(
|
|
||||||
f: FetchLike,
|
|
||||||
username: string,
|
|
||||||
page?: number
|
|
||||||
): Promise<{ user: UserInfoResponse; items: any[]; page: number; total?: number; totalPages?: number; perPage?: number }> {
|
|
||||||
const qs = page && page > 1 ? { page } : undefined
|
|
||||||
const url = buildUrl(`/users/${encodeURIComponent(username)}`, qs as any)
|
|
||||||
const resp = await f(url, { credentials: 'include' })
|
|
||||||
if (!resp.ok) throw new Error(resp.statusText || 'Failed to load profile')
|
|
||||||
const json = (await resp.json()) as UserProfileResponse
|
|
||||||
const items = Array.isArray(json.profile?.parties) ? json.profile.parties : []
|
|
||||||
return {
|
|
||||||
user: json.profile as any,
|
|
||||||
items,
|
|
||||||
page: page || 1,
|
|
||||||
total: json.meta?.count,
|
|
||||||
totalPages: json.meta?.total_pages,
|
|
||||||
perPage: json.meta?.per_page
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import type { PageServerLoad } from './$types'
|
import type { PageServerLoad } from './$types'
|
||||||
import { error } from '@sveltejs/kit'
|
import { error } from '@sveltejs/kit'
|
||||||
import { profile } from '$lib/api/resources/users'
|
import { userAdapter } from '$lib/api/adapters'
|
||||||
import { parseParty } from '$lib/api/schemas/party'
|
import { parseParty } from '$lib/api/schemas/party'
|
||||||
import * as partiesApi from '$lib/api/resources/parties'
|
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ fetch, params, url, depends, locals }) => {
|
export const load: PageServerLoad = async ({ params, url, depends, locals }) => {
|
||||||
depends('app:profile')
|
depends('app:profile')
|
||||||
const username = params.username
|
const username = params.username
|
||||||
const pageParam = url.searchParams.get('page')
|
const pageParam = url.searchParams.get('page')
|
||||||
|
|
@ -14,11 +13,20 @@ export const load: PageServerLoad = async ({ fetch, params, url, depends, locals
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (tab === 'favorites' && isOwner) {
|
if (tab === 'favorites' && isOwner) {
|
||||||
const fav = await partiesApi.favorites(fetch as any, { page })
|
const fav = await userAdapter.getFavorites({ page })
|
||||||
return { user: { username } as any, items: fav.items, page: fav.page, total: fav.total, totalPages: fav.totalPages, perPage: fav.perPage, tab, isOwner }
|
return {
|
||||||
|
user: { username } as any,
|
||||||
|
items: fav.items,
|
||||||
|
page: fav.page,
|
||||||
|
total: fav.total,
|
||||||
|
totalPages: fav.totalPages,
|
||||||
|
perPage: fav.perPage,
|
||||||
|
tab,
|
||||||
|
isOwner
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { user, items, total, totalPages, perPage } = await profile(fetch as any, username, page)
|
const { user, items, total, totalPages, perPage } = await userAdapter.getProfile(username, page)
|
||||||
const parties = items.map((p) => parseParty(p))
|
const parties = items.map((p) => parseParty(p))
|
||||||
return { user, items: parties, page, total, totalPages, perPage, tab, isOwner }
|
return { user, items: parties, page, total, totalPages, perPage, tab, isOwner }
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import type { PageServerLoad } from './$types'
|
import type { PageServerLoad } from './$types'
|
||||||
import { error } from '@sveltejs/kit'
|
import { error } from '@sveltejs/kit'
|
||||||
import * as parties from '$lib/api/resources/parties'
|
import { partyAdapter } from '$lib/api/adapters'
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ fetch, url, depends }) => {
|
export const load: PageServerLoad = async ({ url, depends }) => {
|
||||||
depends('app:parties:list')
|
depends('app:parties:list')
|
||||||
|
|
||||||
const pageParam = url.searchParams.get('page')
|
const pageParam = url.searchParams.get('page')
|
||||||
|
|
@ -12,9 +12,16 @@ export const load: PageServerLoad = async ({ fetch, url, depends }) => {
|
||||||
console.log('[explore/+page.server.ts] Full URL:', url.toString())
|
console.log('[explore/+page.server.ts] Full URL:', url.toString())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { items, total, totalPages, perPage } = await parties.list(fetch, { page })
|
const response = await partyAdapter.list({ page })
|
||||||
console.log('[explore/+page.server.ts] Successfully loaded', items.length, 'parties')
|
console.log('[explore/+page.server.ts] Successfully loaded', response.results.length, 'parties')
|
||||||
return { items, page, total, totalPages, perPage }
|
|
||||||
|
return {
|
||||||
|
items: response.results,
|
||||||
|
page,
|
||||||
|
total: response.total,
|
||||||
|
totalPages: response.totalPages,
|
||||||
|
perPage: response.per || 20
|
||||||
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error('[explore/+page.server.ts] Failed to load teams:', {
|
console.error('[explore/+page.server.ts] Failed to load teams:', {
|
||||||
error: e,
|
error: e,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue