195 lines
6.2 KiB
Plaintext
195 lines
6.2 KiB
Plaintext
---
|
|
import { Icon } from 'astro-icon/components'
|
|
import { actions, isInputError } from 'astro:actions'
|
|
|
|
import BadgeSmall from '../../../components/BadgeSmall.astro'
|
|
import Button from '../../../components/Button.astro'
|
|
import Chat from '../../../components/Chat.astro'
|
|
import InputSelect from '../../../components/InputSelect.astro'
|
|
import ServiceCard from '../../../components/ServiceCard.astro'
|
|
import UserBadge from '../../../components/UserBadge.astro'
|
|
import {
|
|
getServiceSuggestionStatusInfo,
|
|
serviceSuggestionStatuses,
|
|
} from '../../../constants/serviceSuggestionStatus'
|
|
import { getServiceSuggestionTypeInfo } from '../../../constants/serviceSuggestionType'
|
|
import BaseLayout from '../../../layouts/BaseLayout.astro'
|
|
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?.admin) {
|
|
return Astro.redirect(makeLoginUrl(Astro.url, { message: 'Admin access required' }))
|
|
}
|
|
|
|
const serviceSuggestionUpdateResult = Astro.getActionResult(actions.admin.serviceSuggestions.update)
|
|
Astro.locals.banners.addIfSuccess(serviceSuggestionUpdateResult, 'Service suggestion updated successfully')
|
|
const serviceSuggestionUpdateInputErrors = isInputError(serviceSuggestionUpdateResult?.error)
|
|
? serviceSuggestionUpdateResult.error.fields
|
|
: {}
|
|
|
|
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({
|
|
where: {
|
|
id: serviceSuggestionId,
|
|
},
|
|
select: {
|
|
id: true,
|
|
status: true,
|
|
notes: true,
|
|
createdAt: true,
|
|
type: true,
|
|
user: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
displayName: true,
|
|
picture: true,
|
|
},
|
|
},
|
|
service: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
slug: true,
|
|
description: true,
|
|
overallScore: true,
|
|
kycLevel: true,
|
|
imageUrl: true,
|
|
verificationStatus: true,
|
|
acceptedCurrencies: true,
|
|
serviceVisibility: true,
|
|
categories: {
|
|
select: {
|
|
name: true,
|
|
icon: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
messages: {
|
|
select: {
|
|
id: true,
|
|
content: true,
|
|
createdAt: true,
|
|
user: {
|
|
select: {
|
|
id: true,
|
|
displayName: true,
|
|
name: true,
|
|
picture: true,
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: 'desc',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
)
|
|
|
|
if (!serviceSuggestion) {
|
|
return Astro.rewrite('/404')
|
|
}
|
|
|
|
const statusInfo = getServiceSuggestionStatusInfo(serviceSuggestion.status)
|
|
const typeInfo = getServiceSuggestionTypeInfo(serviceSuggestion.type)
|
|
---
|
|
|
|
<BaseLayout
|
|
pageTitle={`${serviceSuggestion.service.name} | Admin Service Suggestion`}
|
|
description="View and manage service suggestion"
|
|
widthClassName="max-w-screen-md"
|
|
htmx
|
|
>
|
|
<h1 class="font-title mt-12 mb-6 text-center text-3xl font-bold">Service suggestion</h1>
|
|
|
|
<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 xs:grid-cols-2 grid gap-2 text-sm sm:grid-cols-3">
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="font-title font-bold">Status:</span>
|
|
<BadgeSmall color={statusInfo.color} text={statusInfo.label} icon={statusInfo.icon} />
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="font-title font-bold">Type:</span>
|
|
<BadgeSmall color={typeInfo.color} text={typeInfo.label} icon={typeInfo.icon} />
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="font-title font-bold">Author:</span>
|
|
<UserBadge class="text-gray-300" user={serviceSuggestion.user} size="md" />
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="font-title font-bold">Submitted:</span>
|
|
<span>
|
|
{
|
|
formatDateShort(serviceSuggestion.createdAt, {
|
|
prefix: false,
|
|
hourPrecision: true,
|
|
caseType: 'sentence',
|
|
})
|
|
}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="font-title font-bold">Service:</span>
|
|
<a href={`/service/${serviceSuggestion.service.slug}`} class="hover:text-day-200 text-green-400">
|
|
Open <Icon name="ri:external-link-line" class="ml-0.5 inline-block size-3 align-[-0.05em]" />
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-night-700 -mx-2 mt-4 rounded-lg p-2 text-sm">
|
|
<span class="font-title block font-bold">Notes for moderators:</span>
|
|
{
|
|
serviceSuggestion.notes ? (
|
|
<div class="mt-1 text-sm wrap-anywhere whitespace-pre-wrap" set:text={serviceSuggestion.notes} />
|
|
) : (
|
|
<div class="text-day-400 my-4 text-center text-sm italic">Empty</div>
|
|
)
|
|
}
|
|
</div>
|
|
|
|
<form method="POST" action={actions.admin.serviceSuggestions.update} class="mt-6 flex items-end gap-2">
|
|
<input type="hidden" name="suggestionId" value={serviceSuggestion.id} />
|
|
<InputSelect
|
|
name="status"
|
|
label="Update status"
|
|
options={serviceSuggestionStatuses.map((status) => ({
|
|
label: status.label,
|
|
value: status.value,
|
|
}))}
|
|
selectProps={{ value: serviceSuggestion.status }}
|
|
class="flex-1"
|
|
error={serviceSuggestionUpdateInputErrors.status}
|
|
/>
|
|
<Button as="button" type="submit" color="success" size="md" icon="ri:save-line" label="Update" />
|
|
</form>
|
|
</section>
|
|
|
|
<Chat
|
|
messages={serviceSuggestion.messages}
|
|
title="Chat with moderators"
|
|
userId={user.id}
|
|
action={actions.admin.serviceSuggestions.message}
|
|
formData={{
|
|
suggestionId: serviceSuggestion.id,
|
|
}}
|
|
class="mt-12"
|
|
/>
|
|
</BaseLayout>
|