refactor: enhance pedidos UI by integrating reusable components for layout and styling, improving code maintainability and user experience across various pages
This commit is contained in:
29
apps/web/src/lib/components/layout/Breadcrumbs.svelte
Normal file
29
apps/web/src/lib/components/layout/Breadcrumbs.svelte
Normal file
@@ -0,0 +1,29 @@
|
||||
<script lang="ts">
|
||||
export type BreadcrumbItem = {
|
||||
label: string;
|
||||
href?: string;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
items: BreadcrumbItem[];
|
||||
class?: string;
|
||||
}
|
||||
|
||||
let { items, class: className = '' }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class={['breadcrumbs mb-4 text-sm', className].filter(Boolean)}>
|
||||
<ul>
|
||||
{#each items as item (item.label)}
|
||||
<li>
|
||||
{#if item.href}
|
||||
<a href={item.href} class="text-primary hover:underline">{item.label}</a>
|
||||
{:else}
|
||||
{item.label}
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
50
apps/web/src/lib/components/layout/PageHeader.svelte
Normal file
50
apps/web/src/lib/components/layout/PageHeader.svelte
Normal file
@@ -0,0 +1,50 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
|
||||
icon?: Snippet;
|
||||
actions?: Snippet;
|
||||
|
||||
class?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
title,
|
||||
subtitle,
|
||||
icon,
|
||||
actions,
|
||||
class: className = ''
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class={['mb-6', className].filter(Boolean)}>
|
||||
<div class="flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center">
|
||||
<div class="flex items-center gap-4">
|
||||
{#if icon}
|
||||
<div class="bg-primary/10 rounded-xl p-3">
|
||||
<div class="text-primary [&_svg]:h-8 [&_svg]:w-8">
|
||||
{@render icon()}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
<h1 class="text-primary text-3xl font-bold">{title}</h1>
|
||||
{#if subtitle}
|
||||
<p class="text-base-content/70">{subtitle}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if actions}
|
||||
<div class="flex items-center gap-2">
|
||||
{@render actions()}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
16
apps/web/src/lib/components/layout/PageShell.svelte
Normal file
16
apps/web/src/lib/components/layout/PageShell.svelte
Normal file
@@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { class: className = '', children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<main class={['container mx-auto flex max-w-7xl flex-col px-4 py-4', className].filter(Boolean)}>
|
||||
{@render children?.()}
|
||||
</main>
|
||||
|
||||
|
||||
34
apps/web/src/lib/components/ui/EmptyState.svelte
Normal file
34
apps/web/src/lib/components/ui/EmptyState.svelte
Normal file
@@ -0,0 +1,34 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
description?: string;
|
||||
icon?: Snippet;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
let { title, description, icon, class: className = '' }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={[
|
||||
'bg-base-100 border-base-300 flex flex-col items-center justify-center rounded-lg border py-12 text-center',
|
||||
className
|
||||
].filter(Boolean)}
|
||||
>
|
||||
{#if icon}
|
||||
<div class="bg-base-200 mb-4 rounded-full p-4">
|
||||
<div class="text-base-content/30 [&_svg]:h-8 [&_svg]:w-8">
|
||||
{@render icon()}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<h3 class="text-lg font-semibold">{title}</h3>
|
||||
{#if description}
|
||||
<p class="text-base-content/60 mt-1 max-w-sm text-sm">{description}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
22
apps/web/src/lib/components/ui/GlassCard.svelte
Normal file
22
apps/web/src/lib/components/ui/GlassCard.svelte
Normal file
@@ -0,0 +1,22 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
bodyClass?: string;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { class: className = '', bodyClass = '', children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={[
|
||||
'card bg-base-100/90 border-base-300 border shadow-xl backdrop-blur-sm',
|
||||
className
|
||||
].filter(Boolean)}
|
||||
>
|
||||
<div class={['card-body', bodyClass].filter(Boolean)}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</div>
|
||||
18
apps/web/src/lib/components/ui/TableCard.svelte
Normal file
18
apps/web/src/lib/components/ui/TableCard.svelte
Normal file
@@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
import GlassCard from '$lib/components/ui/GlassCard.svelte';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
bodyClass?: string;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { class: className = '', bodyClass = '', children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<GlassCard class={className} bodyClass={['p-0', bodyClass].filter(Boolean).join(' ')}>
|
||||
<div class="overflow-x-auto">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</GlassCard>
|
||||
Reference in New Issue
Block a user