Release 202505261445
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
---
|
||||
import { Icon } from 'astro-icon/components'
|
||||
import { Markdown } from 'astro-remote'
|
||||
import { actions, isInputError } from 'astro:actions'
|
||||
import { orderBy } from 'lodash-es'
|
||||
|
||||
@@ -76,6 +77,15 @@ const verificationStepUpdateInputErrors = isInputError(verificationStepUpdateRes
|
||||
const verificationStepDeleteResult = Astro.getActionResult(actions.admin.verificationStep.delete)
|
||||
Astro.locals.banners.addIfSuccess(verificationStepDeleteResult, 'Verification step deleted successfully')
|
||||
|
||||
const internalNoteCreateResult = Astro.getActionResult(actions.admin.service.internalNote.add)
|
||||
Astro.locals.banners.addIfSuccess(internalNoteCreateResult, 'Internal note added successfully')
|
||||
const internalNoteInputErrors = isInputError(internalNoteCreateResult?.error)
|
||||
? internalNoteCreateResult.error.fields
|
||||
: {}
|
||||
|
||||
const internalNoteDeleteResult = Astro.getActionResult(actions.admin.service.internalNote.delete)
|
||||
Astro.locals.banners.addIfSuccess(internalNoteDeleteResult, 'Internal note deleted successfully')
|
||||
|
||||
const [service, categories, attributes] = await Astro.locals.banners.tryMany([
|
||||
[
|
||||
'Error fetching service',
|
||||
@@ -130,6 +140,20 @@ const [service, categories, attributes] = await Astro.locals.banners.tryMany([
|
||||
label: 'asc',
|
||||
},
|
||||
},
|
||||
internalNotes: {
|
||||
include: {
|
||||
addedByUser: {
|
||||
select: {
|
||||
name: true,
|
||||
displayName: true,
|
||||
picture: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: {
|
||||
verificationRequests: true,
|
||||
@@ -290,13 +314,14 @@ if (!service) return Astro.rewrite('/404')
|
||||
</div>
|
||||
|
||||
<InputText
|
||||
label="Referral Code/Link"
|
||||
label="Referral link path"
|
||||
name="referral"
|
||||
inputProps={{
|
||||
value: service.referral ?? undefined,
|
||||
placeholder: 'e.g., REFCODE123 or https://example.com?ref=123',
|
||||
value: service.referral,
|
||||
placeholder: 'e.g. ?ref=123 or /ref/123',
|
||||
}}
|
||||
error={serviceInputErrors.referral}
|
||||
description="Will be appended to the service URL"
|
||||
/>
|
||||
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
@@ -448,6 +473,108 @@ if (!service) return Astro.rewrite('/404')
|
||||
</form>
|
||||
</FormSection>
|
||||
|
||||
<FormSection title="Internal Notes" id="internal-notes">
|
||||
<FormSubSection title="Existing Notes">
|
||||
{
|
||||
service.internalNotes.length === 0 ? (
|
||||
<p class="border-night-600 bg-night-800 text-day-300 rounded-xl border p-6 text-center">
|
||||
No internal notes yet.
|
||||
</p>
|
||||
) : (
|
||||
<div class="space-y-4">
|
||||
{service.internalNotes.map((note) => (
|
||||
<div class="border-night-600 bg-night-800 rounded-md border p-4">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="peer/edit-note sr-only"
|
||||
data-edit-note-checkbox
|
||||
id={`edit-note-${note.id}`}
|
||||
/>
|
||||
|
||||
<div class="flex items-start justify-between">
|
||||
<div class="flex-grow space-y-1">
|
||||
<div
|
||||
data-note-content
|
||||
class="prose text-day-200 prose-sm prose-invert max-w-none text-pretty"
|
||||
>
|
||||
<Markdown content={note.content} />
|
||||
</div>
|
||||
<div class="text-day-500 flex items-center gap-2 text-xs">
|
||||
<TimeFormatted date={note.createdAt} hourPrecision />
|
||||
{note.addedByUser && (
|
||||
<span class="flex items-center gap-1">
|
||||
by <UserBadge user={note.addedByUser} size="sm" />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-1">
|
||||
<Button
|
||||
as="label"
|
||||
for={`edit-note-${note.id}`}
|
||||
variant="faded"
|
||||
size="sm"
|
||||
icon="ri:edit-line"
|
||||
iconOnly
|
||||
label="Edit"
|
||||
/>
|
||||
|
||||
<form method="POST" action={actions.admin.service.internalNote.delete} class="contents">
|
||||
<input type="hidden" name="noteId" value={note.id} />
|
||||
<Button
|
||||
type="submit"
|
||||
size="sm"
|
||||
variant="faded"
|
||||
icon="ri:delete-bin-line"
|
||||
iconOnly
|
||||
label="Delete"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form
|
||||
method="POST"
|
||||
action={actions.admin.service.internalNote.update}
|
||||
data-note-edit-form
|
||||
data-astro-reload
|
||||
class="mt-4 hidden space-y-4 peer-checked/edit-note:block"
|
||||
>
|
||||
<input type="hidden" name="noteId" value={note.id} />
|
||||
<InputTextArea
|
||||
label="Note Content"
|
||||
name="content"
|
||||
value={note.content}
|
||||
inputProps={{ class: 'bg-night-700' }}
|
||||
/>
|
||||
<InputSubmitButton label="Save" icon="ri:save-line" hideCancel />
|
||||
</form>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</FormSubSection>
|
||||
|
||||
<FormSubSection title="Add New Note">
|
||||
<form method="POST" action={actions.admin.service.internalNote.add} class="space-y-4">
|
||||
<input type="hidden" name="serviceId" value={service.id} />
|
||||
<InputTextArea
|
||||
label="Note Content"
|
||||
name="content"
|
||||
inputProps={{
|
||||
required: true,
|
||||
rows: 4,
|
||||
placeholder: 'Add internal note about this service...',
|
||||
}}
|
||||
error={internalNoteInputErrors.content}
|
||||
/>
|
||||
<InputSubmitButton label="Add Note" icon="ri:add-line" hideCancel />
|
||||
</form>
|
||||
</FormSubSection>
|
||||
</FormSection>
|
||||
|
||||
<FormSection title="Events">
|
||||
<FormSubSection title="Existing Events">
|
||||
{
|
||||
@@ -898,7 +1025,7 @@ if (!service) return Astro.rewrite('/404')
|
||||
<Tooltip text="Delete">
|
||||
<form
|
||||
method="POST"
|
||||
action={actions.admin.service.deleteContactMethod}
|
||||
action={actions.admin.service.contactMethod.delete}
|
||||
class="contents"
|
||||
>
|
||||
<input type="hidden" name="id" value={method.id} />
|
||||
@@ -919,7 +1046,7 @@ if (!service) return Astro.rewrite('/404')
|
||||
<form
|
||||
id={`edit-contact-method-${method.id}`}
|
||||
method="POST"
|
||||
action={actions.admin.service.updateContactMethod}
|
||||
action={actions.admin.service.contactMethod.update}
|
||||
class="border-night-500 bg-night-700 mt-3 hidden space-y-3 rounded-md border p-3"
|
||||
>
|
||||
<input type="hidden" name="id" value={method.id} />
|
||||
@@ -954,7 +1081,7 @@ if (!service) return Astro.rewrite('/404')
|
||||
</FormSubSection>
|
||||
|
||||
<FormSubSection title="Add New Contact Method">
|
||||
<form method="POST" action={actions.admin.service.createContactMethod} class="space-y-2">
|
||||
<form method="POST" action={actions.admin.service.contactMethod.add} class="space-y-2">
|
||||
<input type="hidden" name="serviceId" value={service.id} />
|
||||
|
||||
<InputText label="Override Label" name="label" />
|
||||
|
||||
@@ -111,6 +111,7 @@ const services = await Astro.locals.banners.try(
|
||||
_count: {
|
||||
select: {
|
||||
verificationRequests: true,
|
||||
internalNotes: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -440,9 +441,18 @@ const truncate = (text: string, length: number) => {
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<span class="inline-flex items-center rounded-full bg-orange-900/30 px-2.5 py-0.5 text-xs text-orange-400">
|
||||
{service._count.verificationRequests}
|
||||
</span>
|
||||
<div class="flex flex-col items-center justify-center gap-1">
|
||||
<span class="inline-flex items-center rounded-full bg-orange-900/30 px-2.5 py-0.5 text-xs text-orange-400">
|
||||
{service._count.verificationRequests}
|
||||
</span>
|
||||
|
||||
{service._count.internalNotes > 0 && (
|
||||
<span class="inline-flex items-center text-purple-400">
|
||||
<Icon name="ri:sticky-note-line" class="mr-0.5 size-4" />
|
||||
{service._count.internalNotes}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-center text-xs text-zinc-400">{service.formattedDate}</td>
|
||||
<td class="px-4 py-3 text-right">
|
||||
|
||||
@@ -350,13 +350,13 @@ const inputErrors = isInputError(result?.error) ? result.error.fields : {}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="font-title mb-2 block text-sm text-green-500" for="referral">referral</label>
|
||||
<label class="font-title mb-2 block text-sm text-green-500" for="referral">referral link path</label>
|
||||
<input
|
||||
transition:persist
|
||||
type="text"
|
||||
name="referral"
|
||||
id="referral"
|
||||
placeholder="Optional referral code/link"
|
||||
placeholder="e.g. ?ref=123 or /ref/123"
|
||||
class="font-title w-full rounded-md border border-green-500/30 bg-black/50 p-2 text-gray-300 placeholder-gray-500 focus:border-green-500 focus:ring-green-500"
|
||||
/>
|
||||
{
|
||||
@@ -366,6 +366,26 @@ const inputErrors = isInputError(result?.error) ? result.error.fields : {}
|
||||
}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="internalNote" class="font-title mb-2 block text-sm text-green-500">internalNote</label>
|
||||
<div class="space-y-2">
|
||||
<textarea
|
||||
transition:persist
|
||||
name="internalNote"
|
||||
id="internalNote"
|
||||
rows={4}
|
||||
placeholder="Markdown supported"
|
||||
class="font-title w-full rounded-md border border-green-500/30 bg-black/50 p-2 text-gray-300 placeholder-gray-500 focus:border-green-500 focus:ring-green-500"
|
||||
set:text=""
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
inputErrors.internalNote && (
|
||||
<p class="font-title mt-1 text-sm text-red-500">{inputErrors.internalNote.join(', ')}</p>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="font-title inline-flex justify-center rounded-md border border-green-500/30 bg-green-500/10 px-4 py-2 text-sm text-green-400 shadow-xs transition-colors duration-200 hover:bg-green-500/20 focus:ring-2 focus:ring-green-500 focus:ring-offset-2 focus:ring-offset-black focus:outline-hidden"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
import { Icon } from 'astro-icon/components'
|
||||
import { Markdown } from 'astro-remote'
|
||||
import { actions, isInputError } from 'astro:actions'
|
||||
|
||||
import BadgeSmall from '../../../components/BadgeSmall.astro'
|
||||
@@ -304,8 +305,8 @@ if (!user) return Astro.rewrite('/404')
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-note-content>
|
||||
<p class="text-day-200 wrap-anywhere whitespace-pre-wrap" set:text={note.content} />
|
||||
<div data-note-content class="prose prose-sm text-day-200 prose-invert max-w-none text-pretty">
|
||||
<Markdown content={note.content} />
|
||||
</div>
|
||||
|
||||
<form
|
||||
|
||||
Reference in New Issue
Block a user