This commit is contained in:
		
							
								
								
									
										29
									
								
								src/app/admin/feedback/BottomBar.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/app/admin/feedback/BottomBar.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <script lang="ts"> | ||||
|   import Input from '@components/input/Input.svelte'; | ||||
|   import Textarea from '@components/input/Textarea.svelte'; | ||||
|   import type { Feedback } from '@app/admin/feedback/feedback.ts'; | ||||
|  | ||||
|   // types | ||||
|   interface Props { | ||||
|     feedback: Feedback | null; | ||||
|   } | ||||
|  | ||||
|   // inputs | ||||
|   let { feedback }: Props = $props(); | ||||
| </script> | ||||
|  | ||||
| <div | ||||
|   class="absolute bottom-2 bg-base-200 rounded-lg w-[calc(100%-1rem)] mx-2 flex px-6 py-4 gap-10" | ||||
|   hidden={feedback === null} | ||||
| > | ||||
|   <button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2" onclick={() => (feedback = null)}>✕</button> | ||||
|   <div class="w-96"> | ||||
|     <Input value={feedback?.event} label="Event" readonly /> | ||||
|     <Input value={feedback?.title} label="Titel" readonly /> | ||||
|     <Input value={feedback?.username} label="Nutzer" readonly /> | ||||
|   </div> | ||||
|   <div class="divider divider-horizontal"></div> | ||||
|   <div class="w-full"> | ||||
|     <Textarea value={feedback?.content} label="Inhalt" rows={9} readonly dynamicWidth /> | ||||
|   </div> | ||||
| </div> | ||||
							
								
								
									
										41
									
								
								src/app/admin/feedback/Feedback.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/app/admin/feedback/Feedback.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| <script lang="ts"> | ||||
|   import BottomBar from './BottomBar.svelte'; | ||||
|   import { feedbacks, fetchFeedbacks, type Feedback } from '@app/admin/feedback/feedback.ts'; | ||||
|   import { onMount } from 'svelte'; | ||||
|   import DataTable from '@components/admin/table/DataTable.svelte'; | ||||
|  | ||||
|   // consts | ||||
|   const dateFormat = new Intl.DateTimeFormat('de-DE', { | ||||
|     year: 'numeric', | ||||
|     month: '2-digit', | ||||
|     day: '2-digit', | ||||
|     hour: '2-digit', | ||||
|     minute: '2-digit' | ||||
|   }); | ||||
|  | ||||
|   // states | ||||
|   let activeFeedback = $state<Feedback | null>(null); | ||||
|  | ||||
|   // lifecycle | ||||
|   onMount(() => { | ||||
|     fetchFeedbacks(); | ||||
|   }); | ||||
| </script> | ||||
|  | ||||
| {#snippet date(value: string)} | ||||
|   {dateFormat.format(new Date(value))} | ||||
| {/snippet} | ||||
|  | ||||
| <DataTable | ||||
|   data={feedbacks} | ||||
|   count={true} | ||||
|   keys={[ | ||||
|     { key: 'event', label: 'Event', width: 10, sortable: true }, | ||||
|     { key: 'username', label: 'Nutzer', width: 10, sortable: true }, | ||||
|     { key: 'lastChanged', label: 'Datum', width: 10, sortable: true, transform: date }, | ||||
|     { key: 'content', label: 'Inhalt', width: 10 } | ||||
|   ]} | ||||
|   onClick={(feedback) => (activeFeedback = feedback)} | ||||
| /> | ||||
|  | ||||
| <BottomBar feedback={activeFeedback} /> | ||||
							
								
								
									
										21
									
								
								src/app/admin/feedback/feedback.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/app/admin/feedback/feedback.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| import { type ActionReturnType, actions } from 'astro:actions'; | ||||
| import { writable } from 'svelte/store'; | ||||
| import { actionErrorPopup } from '@util/action.ts'; | ||||
|  | ||||
| // types | ||||
| export type Feedbacks = Exclude<ActionReturnType<typeof actions.feedback.feedbacks>['data'], undefined>['feedbacks']; | ||||
| export type Feedback = Feedbacks[0]; | ||||
|  | ||||
| // state | ||||
| export const feedbacks = writable<Feedbacks>([]); | ||||
|  | ||||
| // actions | ||||
| export async function fetchFeedbacks(reporter?: string | null, reported?: string | null) { | ||||
|   const { data, error } = await actions.feedback.feedbacks({ reporter: reporter, reported: reported }); | ||||
|   if (error) { | ||||
|     actionErrorPopup(error); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   feedbacks.set(data.feedbacks); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user