first commit
linter / quality (push) Canceled after 0s
tests / ci (8.3) (push) Canceled after 0s
tests / ci (8.4) (push) Canceled after 0s
tests / ci (8.5) (push) Canceled after 0s

This commit is contained in:
salam committed 2026-10-06 18:53:03 +02:00
commit e687b4437b
418 files changed
+33577

No files matched your search

+102
View File
@@ -0,0 +1,102 @@
<script module lang="ts">
import { index as postsIndex, create as postsCreate } from '@/routes/posts';
export const layout = {
breadcrumbs: [
{ title: 'Posts', href: postsIndex() },
{ title: 'Create Post', href: postsCreate() },
],
};
</script>
<script lang="ts">
import { useForm } from '@inertiajs/svelte';
import { store } from '@/actions/App/Http/Controllers/PostController';
import AppHead from '@/components/AppHead.svelte';
import InputError from '@/components/InputError.svelte';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
const form = useForm({
title: '',
slug: '',
content: '',
status: 'draft',
});
let slugManuallyEdited = false;
function handleTitleInput(e: Event) {
const target = e.target as HTMLInputElement;
form.title = target.value;
if (!slugManuallyEdited) {
form.slug = target.value
.toLowerCase()
.replace(/[\s_]+/g, '-')
.replace(/[^\w-]+/g, '');
}
}
function submit(e: Event) {
e.preventDefault();
form.post(store.url());
}
</script>
<AppHead title="Create Post" />
<div class="w-full space-y-6 p-4">
<h1 class="text-2xl font-bold tracking-tight">Create Post</h1>
<form onsubmit={submit} class="space-y-6">
<div class="grid gap-2">
<Label for="title">Title</Label>
<Input
id="title"
value={form.title}
oninput={handleTitleInput}
required
/>
<InputError message={form.errors.title} />
</div>
<div class="grid gap-2">
<Label for="slug">Slug</Label>
<Input
id="slug"
value={form.slug}
oninput={() => (slugManuallyEdited = true)}
required
/>
<InputError message={form.errors.slug} />
</div>
<div class="grid gap-2">
<Label for="content">Content</Label>
<textarea
id="content"
value={form.content}
rows="10"
required
class="flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
></textarea>
<InputError message={form.errors.content} />
</div>
<div class="grid gap-2">
<Label for="status">Status</Label>
<select
id="status"
bind:value={form.status}
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
>
<option value="draft">Draft</option>
<option value="publish">Publish</option>
</select>
<InputError message={form.errors.status} />
</div>
<Button type="submit" disabled={form.processing}>Create Post</Button>
</form>
</div>
+81
View File
@@ -0,0 +1,81 @@
<script module lang="ts">
import { index as postsIndex } from '@/routes/posts';
export const layout = {
breadcrumbs: [
{ title: 'Posts', href: postsIndex() },
{ title: 'Edit Post', href: postsIndex() },
],
};
</script>
<script lang="ts">
import { useForm } from '@inertiajs/svelte';
import { update } from '@/actions/App/Http/Controllers/PostController';
import AppHead from '@/components/AppHead.svelte';
import InputError from '@/components/InputError.svelte';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
let { post = $bindable() } = $props();
const form = useForm({
title: $state.snapshot(post).title,
slug: $state.snapshot(post).slug,
content: $state.snapshot(post).content,
status: $state.snapshot(post).status,
});
function submit(e: Event) {
e.preventDefault();
form.put(update.url(post.slug));
}
</script>
<AppHead title="Edit Post" />
<div class="w-full space-y-6 p-4">
<h1 class="text-2xl font-bold tracking-tight">Edit Post</h1>
<form onsubmit={submit} class="space-y-6">
<div class="grid gap-2">
<Label for="title">Title</Label>
<Input id="title" value={form.title} required />
<InputError message={form.errors.title} />
</div>
<div class="grid gap-2">
<Label for="slug">Slug</Label>
<Input id="slug" value={form.slug} required />
<InputError message={form.errors.slug} />
</div>
<div class="grid gap-2">
<Label for="content">Content</Label>
<textarea
id="content"
bind:value={form.content}
rows="10"
required
class="flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
></textarea>
<InputError message={form.errors.content} />
</div>
<div class="grid gap-2">
<Label for="status">Status</Label>
<select
id="status"
bind:value={form.status}
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
>
<option value="draft">Draft</option>
<option value="publish">Publish</option>
</select>
<InputError message={form.errors.status} />
</div>
<Button type="submit" disabled={form.processing}>Update Post</Button>
</form>
</div>
+123
View File
@@ -0,0 +1,123 @@
<script module lang="ts">
import { index as postsIndex } from '@/routes/posts';
export const layout = {
breadcrumbs: [
{
title: 'Posts',
href: postsIndex(),
},
],
};
</script>
<script lang="ts">
import { Link, router } from '@inertiajs/svelte';
import {
create as postsCreate,
edit as postsEdit,
destroy as postsDestroy,
} from '@/routes/posts';
import AppHead from '@/components/AppHead.svelte';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { toUrl } from '@/lib/utils';
let { posts } = $props();
function deletePost(post: any) {
if (confirm(`Are you sure you want to delete "${post.title}"?`)) {
router.delete(postsDestroy.url(post.slug));
}
}
</script>
<AppHead title="Posts" />
<div class="w-full space-y-6 p-4">
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold tracking-tight">Posts</h1>
<p class="text-sm text-muted-foreground">Manage your blog posts</p>
</div>
<Button asChild>
{#snippet children(props)}
<Link
{...props}
href={toUrl(postsCreate())}
class={props.class}
>
Create Post
</Link>
{/snippet}
</Button>
</div>
<div class="rounded-lg border">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b bg-muted/50">
<th class="px-4 py-3 text-left font-medium">Title</th>
<th class="px-4 py-3 text-left font-medium">Slug</th>
<th class="px-4 py-3 text-left font-medium">Status</th>
<th class="px-4 py-3 text-right font-medium">Actions</th
>
</tr>
</thead>
<tbody>
{#each posts.data as post (post.id)}
<tr
class="border-b transition-colors hover:bg-muted/50"
>
<td class="px-4 py-3 font-medium">{post.title}</td>
<td class="px-4 py-3 text-muted-foreground"
>{post.slug}</td
>
<td class="px-4 py-3">
<Badge
variant={post.status === 'publish'
? 'default'
: 'secondary'}
>
{post.status}
</Badge>
</td>
<td class="px-4 py-3 text-right">
<div
class="flex items-center justify-end gap-2"
>
<Button variant="outline" size="sm" asChild>
{#snippet children(props)}
<Link
{...props}
href={toUrl(
postsEdit(post.slug),
)}
class={props.class}>Edit</Link
>
{/snippet}
</Button>
<Button
variant="destructive"
size="sm"
onclick={() => deletePost(post)}
>Delete</Button
>
</div>
</td>
</tr>
{:else}
<tr>
<td
colspan="4"
class="px-4 py-8 text-center text-muted-foreground"
>No posts found.</td
>
</tr>
{/each}
</tbody>
</table>
</div>
</div>
</div>
+139
View File
@@ -0,0 +1,139 @@
{
"posts": {
"current_page": 1,
"data": [
{
"id": 30,
"title": "Non et illum sed quibusdam.",
"slug": "non-et-illum-sed-quibusdam",
"content": "Dolore animi dolore tempore. Reprehenderit quasi impedit dolor est dolor quis.\n\nPerspiciatis facere necessitatibus exercitationem praesentium. Odio minus itaque distinctio aut aliquid sed. Dolorem provident quo quae.\n\nNon sint asperiores aut sed. In quis fuga expedita numquam nostrum qui. Odio quasi doloribus impedit commodi itaque quidem recusandae. Voluptates qui hic est veritatis et blanditiis.",
"status": "draft",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T16:28:03.000000Z"
},
{
"id": 29,
"title": "Illum et est maiores enim numquam enim.",
"slug": "illum-et-est-maiores-enim-numquam-enim",
"content": "Magni quo in nulla ut. Sint maxime voluptatem distinctio eaque recusandae. Ullam repudiandae quisquam vel harum quos nulla corrupti. Corporis molestiae incidunt soluta officiis aut assumenda.\n\nVel sit ipsam quia harum. Autem voluptatum assumenda impedit aut. Quos accusamus repellendus est dignissimos eum voluptate dolores nihil. Autem et dolorum quo mollitia ad illum expedita.\n\nLaudantium placeat iure quas laborum a molestiae laudantium. Est officia voluptas dolor quia. Exercitationem possimus facere ducimus. Animi ut molestias quia.",
"status": "publish",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
},
{
"id": 28,
"title": "Nobis sed blanditiis tempore est.",
"slug": "nobis-sed-blanditiis-tempore-est",
"content": "Deleniti quos veniam ut accusantium voluptas quia. Delectus magni fugiat ullam laborum nihil recusandae et. Expedita praesentium fugit dolore et error qui itaque.\n\nQuod nemo adipisci ad officia animi perspiciatis non. Sed fugiat non aliquam eaque adipisci molestias natus. Veniam provident et ut quia.\n\nEst ipsa reiciendis enim numquam cupiditate et et. Soluta dolorem adipisci impedit quos ducimus laudantium. Ipsa est earum distinctio itaque magnam.",
"status": "draft",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
},
{
"id": 27,
"title": "Reiciendis magni consequatur omnis molestiae illo molestiae tempora pariatur.",
"slug": "reiciendis-magni-consequatur-omnis-molestiae-illo-molestiae-tempora-pariatur",
"content": "Quia labore distinctio odio eligendi est sit sit. Saepe qui eveniet optio quis sapiente mollitia provident. Molestias officiis sed possimus velit. Quam laboriosam magni accusantium fugit error quibusdam reprehenderit.\n\nEa omnis aut sit. Ipsam rem iste quo iure illum et facilis. Labore quasi accusantium et qui est.\n\nExcepturi sed qui quibusdam aut quidem est. Earum est qui ea corporis. Et sed nobis nobis tenetur debitis recusandae aut.",
"status": "draft",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
},
{
"id": 26,
"title": "Autem omnis est voluptatem nostrum qui.",
"slug": "autem-omnis-est-voluptatem-nostrum-qui",
"content": "Reiciendis sed explicabo sunt ducimus. Aut vitae ullam itaque voluptatibus ullam aut vel earum. Quis nisi aut magnam sed placeat aperiam hic. Omnis eligendi facilis et et asperiores et.\n\nAssumenda qui vel eius. Facilis est dolores et earum est dolores nisi labore. Cupiditate blanditiis quis perspiciatis. Corporis quam laboriosam iusto voluptas repudiandae aut quas.\n\nPariatur delectus ea vitae voluptate omnis voluptate optio. Quia eum unde maiores tenetur saepe nemo voluptatibus. Exercitationem ad quis illum. Explicabo omnis nemo ut quia alias quidem. Optio numquam assumenda corporis dolore deserunt.",
"status": "publish",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
},
{
"id": 25,
"title": "Provident ipsam non quo culpa.",
"slug": "provident-ipsam-non-quo-culpa",
"content": "Qui harum aut consequatur labore dolores. Quis at suscipit enim expedita ratione commodi. Mollitia praesentium nesciunt assumenda ut pariatur temporibus vel. Et consequatur est possimus autem provident praesentium dolorem.\n\nEnim eius ipsum at provident consequatur vitae. Voluptates magni fuga accusamus animi cupiditate. Aperiam dolorem incidunt itaque aliquam aut minus. Minima maxime labore aut totam expedita aliquam et.\n\nAut repellat et ea in eveniet incidunt voluptas. Qui dolor quam ut et non. Ullam dolorem vitae occaecati.",
"status": "publish",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
},
{
"id": 24,
"title": "Iste enim qui omnis.",
"slug": "iste-enim-qui-omnis",
"content": "Qui dolor consequatur ut itaque quae eum aut aspernatur. Qui porro vitae accusamus sit in nam quia. Nisi laudantium architecto nostrum. Qui eligendi possimus et similique placeat eos.\n\nImpedit atque eos qui tempora qui omnis deserunt. Veniam quae sapiente nam fugit deserunt. Nisi aut dolorem fugiat est dolorem ipsum fugiat.\n\nLibero provident dolore minima quam modi. Excepturi quod sunt alias voluptates sunt. Dolorem facilis quia et recusandae. Fugit officia aut et ullam minima non officia.",
"status": "draft",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
},
{
"id": 23,
"title": "Modi tenetur harum voluptatem accusantium dolorem et dignissimos ut.",
"slug": "modi-tenetur-harum-voluptatem-accusantium-dolorem-et-dignissimos-ut",
"content": "Fugiat magnam eos architecto alias. Id quod odio laudantium quia numquam qui. In qui doloribus quas fugiat voluptates voluptatum ipsum. In voluptates nobis earum distinctio tempora.\n\nIllum blanditiis qui facilis fugit molestiae et nisi. Quasi quaerat omnis et magni illo rerum. In et eveniet et blanditiis est.\n\nLabore non commodi animi doloremque facilis. Eos sunt ut nulla autem alias. Aut sit rerum nesciunt cum quidem exercitationem voluptatem. Suscipit similique quia non fugiat aut.",
"status": "draft",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
},
{
"id": 22,
"title": "Dolores rerum tempore cupiditate minima.",
"slug": "dolores-rerum-tempore-cupiditate-minima",
"content": "Aliquam harum commodi iusto praesentium. Quisquam repellat nihil repellat autem.\n\nEius tempore voluptatibus illo eum et. Excepturi quia porro unde.\n\nEt vitae odit doloremque blanditiis rerum. Rerum eos est aut et eos magnam aut. Deserunt ab animi adipisci molestias eligendi.",
"status": "publish",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
},
{
"id": 21,
"title": "Recusandae aut dolorem velit sit beatae consectetur perspiciatis.",
"slug": "recusandae-aut-dolorem-velit-sit-beatae-consectetur-perspiciatis",
"content": "Aut omnis dolorem maxime laboriosam tempore. Mollitia sunt unde illo. Suscipit voluptatem rerum ut et. Impedit in tenetur quia hic aperiam consequatur modi autem.\n\nVoluptas voluptatem aut alias quae. Commodi praesentium ab similique recusandae. Aliquam aperiam ullam eius consequuntur reiciendis. Est non cupiditate non.\n\nMaxime veritatis inventore sequi nisi. Est ut illo et deserunt aspernatur. Quis quasi porro facilis excepturi est odio vel eum. Quis pariatur eos repellendus enim eos et maiores.",
"status": "draft",
"created_at": "2026-04-15T15:02:18.000000Z",
"updated_at": "2026-04-15T15:02:18.000000Z"
}
],
"first_page_url": "http://dotter.test/posts?page=1",
"from": 1,
"last_page": 3,
"last_page_url": "http://dotter.test/posts?page=3",
"links": [
{
"url": null,
"label": "&laquo; Previous",
"page": null,
"active": false
},
{
"url": "http://dotter.test/posts?page=1",
"label": "1",
"page": 1,
"active": true
},
{
"url": "http://dotter.test/posts?page=2",
"label": "2",
"page": 2,
"active": false
},
{
"url": "http://dotter.test/posts?page=3",
"label": "3",
"page": 3,
"active": false
},
{
"url": "http://dotter.test/posts?page=2",
"label": "Next &raquo;",
"page": 2,
"active": false
}
],
"next_page_url": "http://dotter.test/posts?page=2",
"path": "http://dotter.test/posts",
"per_page": 10,
"prev_page_url": null,
"to": 10,
"total": 30
}
}