refactor(admin): drive media page from server data

This commit is contained in:
Justin Edmund 2025-10-07 05:31:02 -07:00
parent 3a588fdf89
commit 878c0ae248
2 changed files with 73 additions and 28 deletions

View file

@ -0,0 +1,60 @@
import type { Actions, PageServerLoad } from './$types'
import { adminFetchJson } from '$lib/server/admin/authenticated-fetch'
import type { Media } from '@prisma/client'
interface MediaResponse {
media: Media[]
pagination: {
page: number
totalPages: number
total: number
limit: number
hasNext: boolean
hasPrev: boolean
}
}
function buildQueryString(url: URL) {
const params = new URLSearchParams()
const page = url.searchParams.get('page')
if (page) params.set('page', page)
const limit = url.searchParams.get('limit')
if (limit) params.set('limit', limit)
const mimeType = url.searchParams.get('mimeType')
if (mimeType) params.set('mimeType', mimeType)
const publishedFilter = url.searchParams.get('publishedFilter')
if (publishedFilter) params.set('publishedFilter', publishedFilter)
const sort = url.searchParams.get('sort')
if (sort) params.set('sort', sort)
const search = url.searchParams.get('search')
if (search) params.set('search', search)
const albumId = url.searchParams.get('albumId')
if (albumId) params.set('albumId', albumId)
const unused = url.searchParams.get('unused')
if (unused) params.set('unused', unused)
return params.toString()
}
export const load = (async (event) => {
event.depends('admin:media')
const query = buildQueryString(event.url)
const base = query ? `/api/media?${query}` : '/api/media'
const data = await adminFetchJson<MediaResponse>(event, base)
return {
items: data.media,
pagination: data.pagination
}
}) satisfies PageServerLoad
export const actions = {} satisfies Actions

View file

@ -1,5 +1,4 @@
<script lang="ts">
import { onMount } from 'svelte'
import { goto } from '$app/navigation'
import AdminPage from '$lib/components/admin/AdminPage.svelte'
import AdminHeader from '$lib/components/admin/AdminHeader.svelte'
@ -15,13 +14,16 @@
import ChevronDown from '$icons/chevron-down.svg?component'
import PlayIcon from '$icons/play.svg?component'
import type { Media } from '@prisma/client'
import type { PageData } from './$types'
let media = $state<Media[]>([])
let isLoading = $state(true)
const { data } = $props<{ data: PageData }>()
let media = $state<Media[]>(data.items ?? [])
let isLoading = $state(false)
let error = $state('')
let currentPage = $state(1)
let totalPages = $state(1)
let total = $state(0)
let currentPage = $state(data.pagination?.page ?? 1)
let totalPages = $state(data.pagination?.totalPages ?? 1)
let total = $state(data.pagination?.total ?? (data.items?.length ?? 0))
// Only using grid view
// Filter states
@ -70,10 +72,6 @@
// Dropdown state
let isDropdownOpen = $state(false)
onMount(async () => {
await loadMedia()
})
// Watch for search query changes with debounce
$effect(() => {
if (searchQuery !== undefined) {
@ -87,9 +85,6 @@
async function loadMedia(page = 1) {
try {
isLoading = true
const auth = localStorage.getItem('admin_auth')
if (!auth) return
let url = `/api/media?page=${page}&limit=24`
if (filterType !== 'all') {
url += `&mimeType=${filterType}`
@ -105,7 +100,7 @@
}
const response = await fetch(url, {
headers: { Authorization: `Basic ${auth}` }
credentials: 'same-origin'
})
if (!response.ok) throw new Error('Failed to load media')
@ -252,15 +247,12 @@
try {
isDeleting = true
const auth = localStorage.getItem('admin_auth')
if (!auth) return
const response = await fetch('/api/media/bulk-delete', {
method: 'DELETE',
headers: {
Authorization: `Basic ${auth}`,
'Content-Type': 'application/json'
},
credentials: 'same-origin',
body: JSON.stringify({
mediaIds: Array.from(selectedMediaIds)
})
@ -269,8 +261,7 @@
if (!response.ok) {
throw new Error('Failed to delete media files')
}
const result = await response.json()
await response.json()
// Remove deleted media from the list
media = media.filter((m) => !selectedMediaIds.has(m.id))
@ -294,17 +285,14 @@
if (selectedMediaIds.size === 0) return
try {
const auth = localStorage.getItem('admin_auth')
if (!auth) return
// Update each selected media item
const promises = Array.from(selectedMediaIds).map(async (mediaId) => {
const response = await fetch(`/api/media/${mediaId}`, {
method: 'PUT',
headers: {
Authorization: `Basic ${auth}`,
'Content-Type': 'application/json'
},
credentials: 'same-origin',
body: JSON.stringify({ isPhotography: true })
})
@ -335,17 +323,14 @@
if (selectedMediaIds.size === 0) return
try {
const auth = localStorage.getItem('admin_auth')
if (!auth) return
// Update each selected media item
const promises = Array.from(selectedMediaIds).map(async (mediaId) => {
const response = await fetch(`/api/media/${mediaId}`, {
method: 'PUT',
headers: {
Authorization: `Basic ${auth}`,
'Content-Type': 'application/json'
},
credentials: 'same-origin',
body: JSON.stringify({ isPhotography: false })
})