Release 2025-05-19
This commit is contained in:
163
web/src/pages/service-suggestion/[id].astro
Normal file
163
web/src/pages/service-suggestion/[id].astro
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
import { Icon } from 'astro-icon/components'
|
||||
import { actions } from 'astro:actions'
|
||||
|
||||
import AdminOnly from '../../components/AdminOnly.astro'
|
||||
import Chat from '../../components/Chat.astro'
|
||||
import ServiceCard from '../../components/ServiceCard.astro'
|
||||
import { getServiceSuggestionStatusInfo } from '../../constants/serviceSuggestionStatus'
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro'
|
||||
import { cn } from '../../lib/cn'
|
||||
import { parseIntWithFallback } from '../../lib/numbers'
|
||||
import { prisma } from '../../lib/prisma'
|
||||
import { makeLoginUrl } from '../../lib/redirectUrls'
|
||||
import { formatDateShort } from '../../lib/timeAgo'
|
||||
|
||||
const user = Astro.locals.user
|
||||
if (!user) {
|
||||
return Astro.redirect(makeLoginUrl(Astro.url, { message: 'Login to view service suggestion' }))
|
||||
}
|
||||
|
||||
const { id: serviceSuggestionIdRaw } = Astro.params
|
||||
const serviceSuggestionId = parseIntWithFallback(serviceSuggestionIdRaw)
|
||||
if (!serviceSuggestionId) {
|
||||
return Astro.rewrite('/404')
|
||||
}
|
||||
|
||||
const serviceSuggestion = await Astro.locals.banners.try('Error fetching service suggestion', async () =>
|
||||
prisma.serviceSuggestion.findUnique({
|
||||
select: {
|
||||
id: true,
|
||||
status: true,
|
||||
notes: true,
|
||||
createdAt: true,
|
||||
service: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
description: true,
|
||||
overallScore: true,
|
||||
kycLevel: true,
|
||||
imageUrl: true,
|
||||
verificationStatus: true,
|
||||
acceptedCurrencies: true,
|
||||
categories: {
|
||||
select: {
|
||||
name: true,
|
||||
icon: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
select: {
|
||||
id: true,
|
||||
content: true,
|
||||
createdAt: true,
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
picture: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
id: serviceSuggestionId,
|
||||
userId: user.id,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
if (!serviceSuggestion) {
|
||||
if (user.admin) return Astro.redirect(`/admin/service-suggestions/${serviceSuggestionIdRaw}`)
|
||||
return Astro.rewrite('/404')
|
||||
}
|
||||
|
||||
const statusInfo = getServiceSuggestionStatusInfo(serviceSuggestion.status)
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
pageTitle={`${serviceSuggestion.service.name} | Service suggestion`}
|
||||
description="View your service suggestion"
|
||||
ogImage={{ template: 'generic', title: serviceSuggestion.service.name }}
|
||||
widthClassName="max-w-screen-md"
|
||||
htmx
|
||||
breadcrumbs={[
|
||||
{
|
||||
name: 'Service suggestions',
|
||||
url: '/service-suggestion',
|
||||
},
|
||||
{
|
||||
name: `${serviceSuggestion.service.name} | Service suggestion`,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<h1 class="font-title mt-12 mb-6 text-center text-3xl font-bold">Edit service</h1>
|
||||
|
||||
<AdminOnly>
|
||||
<a
|
||||
href={`/admin/service-suggestions/${serviceSuggestionIdRaw}`}
|
||||
class="border-day-500/30 bg-day-500/10 text-day-400 hover:bg-day-500/20 focus:ring-day-500 inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm shadow-xs transition-colors duration-200 focus:ring-2 focus:ring-offset-2 focus:ring-offset-black focus:outline-hidden"
|
||||
>
|
||||
<Icon name="ri:lock-line" class="size-4" />
|
||||
View in admin
|
||||
</a>
|
||||
</AdminOnly>
|
||||
|
||||
<ServiceCard service={serviceSuggestion.service} class="mb-6" />
|
||||
|
||||
<section class="border-night-400 bg-night-600 rounded-lg border p-6">
|
||||
<div class="text-day-200 grid grid-cols-2 gap-6 text-sm">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span>Status:</span>
|
||||
<span
|
||||
class={cn(
|
||||
'border-night-500 bg-night-800 box-content inline-flex h-8 items-center justify-center gap-1 rounded-full border px-2',
|
||||
statusInfo.iconClass
|
||||
)}
|
||||
>
|
||||
<Icon name={statusInfo.icon} class="size-4" />
|
||||
{statusInfo.label}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span>Submitted:</span>
|
||||
<span>
|
||||
{
|
||||
formatDateShort(serviceSuggestion.createdAt, {
|
||||
prefix: false,
|
||||
hourPrecision: true,
|
||||
caseType: 'sentence',
|
||||
})
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<div class="text-day-200 mb-2 text-sm">Notes for moderators:</div>
|
||||
<div class="text-sm whitespace-pre-wrap">
|
||||
{serviceSuggestion.notes ?? <span class="italic">Empty</span>}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Chat
|
||||
messages={serviceSuggestion.messages}
|
||||
title="Chat with moderators"
|
||||
userId={user.id}
|
||||
action={actions.serviceSuggestion.message}
|
||||
formData={{
|
||||
suggestionId: serviceSuggestion.id,
|
||||
}}
|
||||
class="mt-12"
|
||||
/>
|
||||
</BaseLayout>
|
||||
Reference in New Issue
Block a user