--- import { EventType, VerificationStepStatus } from '@prisma/client' import { Icon } from 'astro-icon/components' import { actions, isInputError } from 'astro:actions' import InputCardGroup from '../../../../components/InputCardGroup.astro' import InputCheckboxGroup from '../../../../components/InputCheckboxGroup.astro' import InputImageFile from '../../../../components/InputImageFile.astro' import InputSubmitButton from '../../../../components/InputSubmitButton.astro' import InputText from '../../../../components/InputText.astro' import InputTextArea from '../../../../components/InputTextArea.astro' import UserBadge from '../../../../components/UserBadge.astro' import { formatContactMethod } from '../../../../constants/contactMethods' import { currencies } from '../../../../constants/currencies' import { kycLevels } from '../../../../constants/kycLevels' import { serviceVisibilities } from '../../../../constants/serviceVisibility' import { verificationStatuses } from '../../../../constants/verificationStatus' import BaseLayout from '../../../../layouts/BaseLayout.astro' import { cn } from '../../../../lib/cn' import { prisma } from '../../../../lib/prisma' const { slug } = Astro.params const serviceResult = Astro.getActionResult(actions.admin.service.update) const eventCreateResult = Astro.getActionResult(actions.admin.event.create) const eventToggleResult = Astro.getActionResult(actions.admin.event.toggle) const eventDeleteResult = Astro.getActionResult(actions.admin.event.delete) const eventUpdateResult = Astro.getActionResult(actions.admin.event.update) const verificationStepCreateResult = Astro.getActionResult(actions.admin.verificationStep.create) const verificationStepUpdateResult = Astro.getActionResult(actions.admin.verificationStep.update) const verificationStepDeleteResult = Astro.getActionResult(actions.admin.verificationStep.delete) Astro.locals.banners.addIfSuccess(serviceResult, 'Service updated successfully') Astro.locals.banners.addIfSuccess(eventCreateResult, 'Event created successfully') Astro.locals.banners.addIfSuccess(eventToggleResult, 'Event visibility updated successfully') Astro.locals.banners.addIfSuccess(eventDeleteResult, 'Event deleted successfully') Astro.locals.banners.addIfSuccess(eventUpdateResult, 'Event updated successfully') Astro.locals.banners.addIfSuccess(verificationStepCreateResult, 'Verification step added successfully') Astro.locals.banners.addIfSuccess(verificationStepUpdateResult, 'Verification step updated successfully') Astro.locals.banners.addIfSuccess(verificationStepDeleteResult, 'Verification step deleted successfully') if (serviceResult && !serviceResult.error && slug !== serviceResult.data.service.slug) { return Astro.redirect(`/admin/services/${serviceResult.data.service.slug}/edit`) } const serviceInputErrors = isInputError(serviceResult?.error) ? serviceResult.error.fields : {} const eventInputErrors = isInputError(eventCreateResult?.error) ? eventCreateResult.error.fields : {} const eventUpdateInputErrors = isInputError(eventUpdateResult?.error) ? eventUpdateResult.error.fields : {} const verificationStepInputErrors = isInputError(verificationStepCreateResult?.error) ? verificationStepCreateResult.error.fields : {} const verificationStepUpdateInputErrors = isInputError(verificationStepUpdateResult?.error) ? verificationStepUpdateResult.error.fields : {} if (!slug) return Astro.rewrite('/404') const service = await Astro.locals.banners.try('Error fetching service', () => prisma.service.findUnique({ where: { slug }, include: { attributes: { select: { attribute: { select: { id: true, }, }, }, }, categories: { select: { id: true, }, }, events: { orderBy: { startedAt: 'desc', }, }, verificationRequests: { select: { id: true, user: { select: { name: true, displayName: true, picture: true, }, }, createdAt: true, }, orderBy: { createdAt: 'desc', }, }, verificationSteps: { orderBy: { createdAt: 'desc', }, }, contactMethods: { orderBy: { label: 'asc', }, }, _count: { select: { verificationRequests: true, }, }, }, }) ) if (!service) return Astro.rewrite('/404') const categories = await Astro.locals.banners.try( 'Error fetching categories', () => prisma.category.findMany({ orderBy: { name: 'asc' }, }), [] ) const attributes = await Astro.locals.banners.try( 'Error fetching attributes', () => prisma.attribute.findMany({ orderBy: { category: 'asc' }, }), [] ) // Button style constants for admin sections (Events, etc.) const buttonPrimaryClasses = 'inline-flex items-center justify-center rounded-md border border-transparent bg-sky-600 px-3 py-1.5 text-sm font-medium text-white shadow-sm hover:bg-sky-700 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2 focus:ring-offset-zinc-900' const buttonSmallBaseClasses = 'rounded-md px-2 py-1 text-xs font-medium' const buttonSmallPrimaryClasses = cn( buttonSmallBaseClasses, 'text-sky-400 hover:bg-sky-700/30 hover:text-sky-300' ) const buttonSmallSecondaryClasses = cn( buttonSmallBaseClasses, 'text-zinc-400 hover:bg-zinc-700/50 hover:text-zinc-300' ) const buttonSmallDestructiveClasses = cn( buttonSmallBaseClasses, 'text-red-400 hover:bg-red-700/30 hover:text-red-300' ) const buttonSmallWarningClasses = cn( buttonSmallBaseClasses, 'text-yellow-400 hover:bg-yellow-700/30 hover:text-yellow-300' ) // Legacy classes for existing admin forms (Events, Verification Steps, Contact Methods) const inputBaseClasses = 'w-full rounded-md border-zinc-600 bg-zinc-700/80 p-2 text-zinc-200 placeholder-zinc-400 focus:border-sky-500 focus:ring-1 focus:ring-sky-500 text-sm' const labelBaseClasses = 'block text-sm font-medium text-zinc-300 mb-1' const errorTextClasses = 'mt-1 text-xs text-red-400' ---

Editing {service.name} [{service.id}]

View Service Page

Service Details

({ label: category.name, value: category.id.toString(), icon: category.icon, }))} selectedValues={service.categories.map((c) => c.id.toString())} error={serviceInputErrors.categories} />
({ label: `${kycLevel.name} (${kycLevel.value}/4)`, value: kycLevel.id.toString(), icon: kycLevel.icon, description: kycLevel.description, }))} selectedValue={service.kycLevel.toString()} iconSize="md" cardSize="md" error={serviceInputErrors.kycLevel} class="[&>div]:grid-cols-2 [&>div]:[--card-min-size:16rem]" />
({ label: `${attribute.title} (${attribute.category})`, value: attribute.id.toString(), }))} selectedValues={service.attributes.map((a) => a.attribute.id.toString())} error={serviceInputErrors.attributes} />
({ label: status.label, value: status.value, icon: status.icon, iconClass: status.classNames.icon, description: status.description, }))} selectedValue={service.verificationStatus} error={serviceInputErrors.verificationStatus} cardSize="md" iconSize="md" class="[&>div]:grid-cols-2 [&>div]:[--card-min-size:16rem]" />
({ label: currency.name, value: currency.id, icon: currency.icon, }))} selectedValue={service.acceptedCurrencies} error={serviceInputErrors.acceptedCurrencies} required multiple />
({ label: visibility.label, value: visibility.value, icon: visibility.icon, iconClass: visibility.iconClass, description: visibility.description, }))} selectedValue={service.serviceVisibility} error={serviceInputErrors.serviceVisibility} cardSize="sm" />

Events

{ service.events.length > 0 && (

Existing Events

{service.events.map((event) => (
{event.title} {event.type} {!event.visible && ( Hidden )}

{event.content}

Started: {new Date(event.startedAt).toLocaleDateString()} Ended: {event.endedAt ? event.endedAt === event.startedAt ? '1-time event' : new Date(event.endedAt).toLocaleDateString() : 'Ongoing'} {event.source && Source: {event.source}}
{/* Edit Event Form - Hidden by default */}