Release 2025-05-19
This commit is contained in:
@@ -1,174 +0,0 @@
|
||||
---
|
||||
import { Icon } from 'astro-icon/components'
|
||||
import { actions } from 'astro:actions'
|
||||
import { Picture } from 'astro:assets'
|
||||
import { z } from 'astro:content'
|
||||
|
||||
import defaultServiceImage from '../../assets/fallback-service-image.jpg'
|
||||
import Button from '../../components/Button.astro'
|
||||
import TimeFormatted from '../../components/TimeFormatted.astro'
|
||||
import Tooltip from '../../components/Tooltip.astro'
|
||||
import {
|
||||
getServiceSuggestionStatusInfo,
|
||||
serviceSuggestionStatuses,
|
||||
} from '../../constants/serviceSuggestionStatus'
|
||||
import { getServiceSuggestionTypeInfo } from '../../constants/serviceSuggestionType'
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro'
|
||||
import { zodEnumFromConstant } from '../../lib/arrays'
|
||||
import { cn } from '../../lib/cn'
|
||||
import { zodParseQueryParamsStoringErrors } from '../../lib/parseUrlFilters'
|
||||
import { prisma } from '../../lib/prisma'
|
||||
import { makeLoginUrl } from '../../lib/redirectUrls'
|
||||
|
||||
const user = Astro.locals.user
|
||||
if (!user) {
|
||||
return Astro.redirect(makeLoginUrl(Astro.url, { message: 'Login to manage service suggestions' }))
|
||||
}
|
||||
|
||||
const { data: filters } = zodParseQueryParamsStoringErrors(
|
||||
{
|
||||
serviceId: z.array(z.number().int().positive()).default([]),
|
||||
status: z.array(zodEnumFromConstant(serviceSuggestionStatuses, 'value')).default([]),
|
||||
},
|
||||
Astro
|
||||
)
|
||||
|
||||
const serviceSuggestions = await Astro.locals.banners.try('Error fetching service suggestions', async () =>
|
||||
prisma.serviceSuggestion.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
type: true,
|
||||
status: true,
|
||||
createdAt: true,
|
||||
service: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
imageUrl: true,
|
||||
verificationStatus: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
id: filters.serviceId.length > 0 ? { in: filters.serviceId } : undefined,
|
||||
status: filters.status.length > 0 ? { in: filters.status } : undefined,
|
||||
userId: user.id,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
if (!serviceSuggestions) {
|
||||
return Astro.rewrite('/404')
|
||||
}
|
||||
|
||||
const createResult = Astro.getActionResult(actions.serviceSuggestion.createService)
|
||||
const success = !!createResult && !createResult.error
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
pageTitle="My service suggestions"
|
||||
description="Manage your service suggestions"
|
||||
ogImage={{ template: 'generic', title: 'Service suggestions' }}
|
||||
widthClassName="max-w-screen-md"
|
||||
breadcrumbs={[
|
||||
{
|
||||
name: 'Service suggestions',
|
||||
url: '/service-suggestion',
|
||||
},
|
||||
{
|
||||
name: 'My suggestions',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<div
|
||||
class="xs:flex-row xs:flex-wrap xs:justify-between mb-8 flex flex-col items-center justify-center gap-4 text-center sm:mt-8"
|
||||
>
|
||||
<h1 class="font-title text-day-100 text-3xl">Service suggestions</h1>
|
||||
<Button as="a" href="/service-suggestion/new" label="Create" icon="ri:add-line" />
|
||||
</div>
|
||||
|
||||
{
|
||||
success && (
|
||||
<div class="mb-8 rounded-lg border border-green-500/30 bg-green-950 p-4 text-sm text-green-500">
|
||||
<Icon name="ri:check-line" class="mr-2 inline-block size-4 text-green-500" />
|
||||
Service suggestion submitted successfully!
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
serviceSuggestions.length === 0 ? (
|
||||
<p class="text-day-400">No suggestions yet.</p>
|
||||
) : (
|
||||
<div class="-mx-4 overflow-x-auto px-4">
|
||||
<div class="grid w-full min-w-min grid-cols-[1fr_auto_auto_auto_auto] place-content-center place-items-center gap-x-4 gap-y-2">
|
||||
<p class="place-self-start">Service</p>
|
||||
<p>Type</p>
|
||||
<p>Status</p>
|
||||
<p>Created</p>
|
||||
<p>Actions</p>
|
||||
|
||||
{serviceSuggestions.map((suggestion) => {
|
||||
const typeInfo = getServiceSuggestionTypeInfo(suggestion.type)
|
||||
const statusInfo = getServiceSuggestionStatusInfo(suggestion.status)
|
||||
|
||||
return (
|
||||
<>
|
||||
<a
|
||||
href={`/service/${suggestion.service.slug}`}
|
||||
class="inline-flex w-full min-w-32 items-center gap-2 hover:underline"
|
||||
>
|
||||
<Picture
|
||||
src={suggestion.service.imageUrl ?? (defaultServiceImage as unknown as string)}
|
||||
alt={suggestion.service.name}
|
||||
width={32}
|
||||
height={32}
|
||||
class="inline-block size-8 min-w-8 shrink-0 rounded-md"
|
||||
formats={['jxl', 'avif', 'webp']}
|
||||
/>
|
||||
<span class="shrink truncate">{suggestion.service.name}</span>
|
||||
</a>
|
||||
|
||||
<Tooltip
|
||||
as="span"
|
||||
class="inline-flex items-center gap-1"
|
||||
text={typeInfo.label}
|
||||
classNames={{ tooltip: 'md:hidden!' }}
|
||||
>
|
||||
<Icon name={typeInfo.icon} class="size-4" />
|
||||
<span class="hidden md:inline">{typeInfo.label}</span>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
as="span"
|
||||
text={statusInfo.label}
|
||||
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
|
||||
)}
|
||||
classNames={{ tooltip: 'md:hidden!' }}
|
||||
>
|
||||
<Icon name={statusInfo.icon} class="size-4" />
|
||||
<span class="hidden md:inline">{statusInfo.label}</span>
|
||||
</Tooltip>
|
||||
|
||||
<TimeFormatted date={suggestion.createdAt} caseType="sentence" prefix={false} />
|
||||
|
||||
<Button
|
||||
as="a"
|
||||
href={`/service-suggestion/${suggestion.id}`}
|
||||
label="View"
|
||||
icon="ri:eye-line"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</BaseLayout>
|
||||
Reference in New Issue
Block a user