--- import { Icon } from 'astro-icon/components' import { actions } from 'astro:actions' import { z } from 'astro:content' import { orderBy } from 'lodash-es' import BadgeSmall from '../../../components/BadgeSmall.astro' import Button from '../../../components/Button.astro' import SortArrowIcon from '../../../components/SortArrowIcon.astro' import TimeFormatted from '../../../components/TimeFormatted.astro' import Tooltip from '../../../components/Tooltip.astro' import UserBadge from '../../../components/UserBadge.astro' import { getServiceSuggestionStatusInfo, serviceSuggestionStatuses, serviceSuggestionStatusesZodEnumBySlug, serviceSuggestionStatusSlugToId, } from '../../../constants/serviceSuggestionStatus' import { getServiceSuggestionTypeInfo, serviceSuggestionTypes, serviceSuggestionTypeSlugToId, serviceSuggestionTypesZodEnumBySlug, } from '../../../constants/serviceSuggestionType' import BaseLayout from '../../../layouts/BaseLayout.astro' import { zodParseQueryParamsStoringErrors } from '../../../lib/parseUrlFilters' import { prisma } from '../../../lib/prisma' import { makeLoginUrl } from '../../../lib/redirectUrls' import type { Prisma } from '@prisma/client' const user = Astro.locals.user if (!user?.admin) { return Astro.redirect(makeLoginUrl(Astro.url, { message: 'Admin access required' })) } const { data: filters } = zodParseQueryParamsStoringErrors( { search: z.string().optional(), status: serviceSuggestionStatusesZodEnumBySlug .transform((slug) => serviceSuggestionStatusSlugToId(slug)) .optional(), type: serviceSuggestionTypesZodEnumBySlug .transform((slug) => serviceSuggestionTypeSlugToId(slug)) .optional(), 'sort-by': z .enum(['service', 'status', 'type', 'user', 'createdAt', 'messageCount']) .default('createdAt'), 'sort-order': z.enum(['asc', 'desc']).default('desc'), }, Astro ) let prismaOrderBy: Prisma.ServiceSuggestionOrderByWithRelationInput = { createdAt: 'desc' } if (filters['sort-by'] === 'createdAt') { prismaOrderBy = { createdAt: filters['sort-order'] } } let suggestions = await prisma.serviceSuggestion.findMany({ where: { ...(filters.search ? { OR: [ { service: { name: { contains: filters.search, mode: 'insensitive' } } }, { user: { name: { contains: filters.search, mode: 'insensitive' } } }, { notes: { contains: filters.search, mode: 'insensitive' } }, ], } : {}), status: filters.status, type: filters.type, }, orderBy: prismaOrderBy, select: { id: true, type: true, status: true, notes: true, createdAt: true, user: { select: { displayName: true, name: true, picture: true, }, }, service: { select: { id: true, name: true, slug: true, description: true, imageUrl: true, verificationStatus: true, categories: { select: { name: true, icon: true, }, }, }, }, messages: { select: { id: true, content: true, createdAt: true, user: { select: { id: true, name: true, }, }, }, orderBy: { createdAt: 'desc', }, take: 1, }, _count: { select: { messages: true, }, }, }, }) let suggestionsWithDetails = suggestions.map((s) => ({ ...s, statusInfo: getServiceSuggestionStatusInfo(s.status), typeInfo: getServiceSuggestionTypeInfo(s.type), messageCount: s._count.messages, lastMessage: s.messages[0], })) if (filters['sort-by'] === 'service') { suggestionsWithDetails = orderBy( suggestionsWithDetails, [(s) => s.service.name.toLowerCase()], [filters['sort-order']] ) } else if (filters['sort-by'] === 'status') { suggestionsWithDetails = orderBy( suggestionsWithDetails, [(s) => s.statusInfo.label], [filters['sort-order']] ) } else if (filters['sort-by'] === 'type') { suggestionsWithDetails = orderBy(suggestionsWithDetails, [(s) => s.typeInfo.label], [filters['sort-order']]) } else if (filters['sort-by'] === 'user') { suggestionsWithDetails = orderBy( suggestionsWithDetails, [(s) => s.user.name.toLowerCase()], [filters['sort-order']] ) } else if (filters['sort-by'] === 'messageCount') { suggestionsWithDetails = orderBy(suggestionsWithDetails, ['messageCount'], [filters['sort-order']]) } const suggestionCount = suggestionsWithDetails.length const makeSortUrl = (slug: string) => { const currentSortBy = filters['sort-by'] const currentSortOrder = filters['sort-order'] const newSortOrder = currentSortBy === slug && currentSortOrder === 'asc' ? 'desc' : 'asc' const searchParams = new URLSearchParams(Astro.url.search) searchParams.set('sort-by', slug) searchParams.set('sort-order', newSortOrder) return `/admin/service-suggestions?${searchParams.toString()}` } --- Service Suggestions {suggestionCount} suggestions Search Status All Statuses { serviceSuggestionStatuses.map((status) => ( {status.label} )) } Type All Types { serviceSuggestionTypes.map((type) => ( {type.label} )) } Suggestions List Scroll horizontally to see more → Service User Type Status Created Messages Actions { suggestionsWithDetails.map((suggestion) => ( {suggestion.service.name} {suggestion.service.description} {serviceSuggestionStatuses.map((status) => ( {status.label} ))} {suggestion.messageCount} )) }