first commit
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled

This commit is contained in:
2025-04-23 00:14:33 +06:00
commit 356f56eebd
197 changed files with 21536 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
@props([
'on',
])
<div
x-data="{ shown: false, timeout: null }"
x-init="@this.on('{{ $on }}', () => { clearTimeout(timeout); shown = true; timeout = setTimeout(() => { shown = false }, 2000); })"
x-show.transition.out.opacity.duration.1500ms="shown"
x-transition:leave.opacity.duration.1500ms
style="display: none"
{{ $attributes->merge(['class' => 'text-sm']) }}
>
{{ $slot->isEmpty() ? __('Saved.') : $slot }}
</div>

View File

@@ -0,0 +1,16 @@
<!-- resources/views/components/activity-icon.blade.php -->
@props(['type'])
@php
$icons = [
'upload' => 'document-upload',
'approval' => 'shield-check',
'comment' => 'chat-alt',
'update' => 'pencil-alt',
'delete' => 'trash'
];
$defaultIcon = 'bell';
@endphp
<x-icons :icon="$icons[$type] ?? $defaultIcon" class="w-5 h-5 text-gray-400" />

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 42" {{ $attributes }}>
<path
fill="currentColor"
fill-rule="evenodd"
clip-rule="evenodd"
d="M17.2 5.633 8.6.855 0 5.633v26.51l16.2 9 16.2-9v-8.442l7.6-4.223V9.856l-8.6-4.777-8.6 4.777V18.3l-5.6 3.111V5.633ZM38 18.301l-5.6 3.11v-6.157l5.6-3.11V18.3Zm-1.06-7.856-5.54 3.078-5.54-3.079 5.54-3.078 5.54 3.079ZM24.8 18.3v-6.157l5.6 3.111v6.158L24.8 18.3Zm-1 1.732 5.54 3.078-13.14 7.302-5.54-3.078 13.14-7.3v-.002Zm-16.2 7.89 7.6 4.222V38.3L2 30.966V7.92l5.6 3.111v16.892ZM8.6 9.3 3.06 6.222 8.6 3.143l5.54 3.08L8.6 9.3Zm21.8 15.51-13.2 7.334V38.3l13.2-7.334v-6.156ZM9.6 11.034l5.6-3.11v14.6l-5.6 3.11v-14.6Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 714 B

View File

@@ -0,0 +1,6 @@
<div class="flex aspect-square size-8 items-center justify-center rounded-md bg-accent-content text-accent-foreground">
<x-app-logo-icon class="size-5 fill-current text-white dark:text-black" />
</div>
<div class="ms-1 grid flex-1 text-start text-sm">
<span class="mb-0.5 truncate leading-none font-semibold">Laravel Starter Kit</span>
</div>

View File

@@ -0,0 +1,9 @@
@props([
'title',
'description',
])
<div class="flex w-full flex-col text-center">
<flux:heading size="xl">{{ $title }}</flux:heading>
<flux:subheading>{{ $description }}</flux:subheading>
</div>

View File

@@ -0,0 +1,9 @@
@props([
'status',
])
@if ($status)
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600']) }}>
{{ $status }}
</div>
@endif

View File

@@ -0,0 +1,8 @@
<!-- resources/views/components/checkbox.blade.php -->
@props(['disabled' => false])
<input
type="checkbox"
{{ $disabled ? 'disabled' : '' }}
{!! $attributes->merge(['class' => 'rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50'])
!!}>

View File

@@ -0,0 +1,27 @@
<!-- resources/views/components/confirmation-modal.blade.php -->
@props(['show' => false])
<div x-data="{ show: @entangle($attributes->wire('model')) }"
x-show="show"
class="fixed inset-0 z-50 overflow-y-auto">
<!-- Fondo oscuro -->
<div class="fixed inset-0 bg-black opacity-50"></div>
<!-- Contenido del modal -->
<div class="min-h-screen flex items-center justify-center p-4">
<div @click.away="show = false"
class="bg-white rounded-lg overflow-hidden shadow-xl max-w-md w-full">
<div class="px-6 py-4 border-b">
<h3 class="text-lg font-medium text-gray-900">{{ $title }}</h3>
</div>
<div class="px-6 py-4">
{{ $content }}
</div>
<div class="px-6 py-4 bg-gray-50 flex justify-end space-x-4">
{{ $footer }}
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,6 @@
@props(['href' => '#'])
<a {{ $attributes->merge(['class' => 'block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100']) }}
href="{{ $href }}">
{{ $slot }}
</a>

View File

@@ -0,0 +1,22 @@
@props(['folder', 'level' => 0])
<li class="pl-{{ $level * 4 }} group">
<div class="flex items-center justify-between p-2 hover:bg-gray-50 rounded-lg cursor-pointer"
wire:click="$emit('folderSelected', {{ $folder->id }})">
<div class="flex items-center">
<x-icons icon="folder" class="w-5 h-5 mr-2 text-yellow-500" />
<span class="text-sm">{{ $folder->name }}</span>
</div>
@if($folder->children->isNotEmpty())
<x-icons icon="chevron-right" class="w-4 h-4 text-gray-400 transform group-hover:rotate-90 transition-transform" />
@endif
</div>
@if($folder->children->isNotEmpty())
<ul class="mt-1 space-y-1">
@foreach($folder->children as $child)
<x-folder-item :folder="$child" :level="$level + 1" />
@endforeach
</ul>
@endif
</li>

View File

@@ -0,0 +1,34 @@
@props(['folder', 'selectedFolderId', 'expandedFolders', 'level' => 0])
<li class="pl-{{ $level * 2 }}">
<div class="flex items-center justify-between p-2 rounded hover:bg-gray-100 {{ $folder->id == $selectedFolderId ? 'bg-blue-50 border border-blue-200' : '' }}">
<div class="flex items-center flex-1" wire:click="selectFolder({{ $folder->id }})">
<button wire:click.prevent="toggleFolder({{ $folder->id }})" class="mr-2">
@if(in_array($folder->id, $expandedFolders))
<x-icons.chevron-down class="w-4 h-4 text-gray-400" />
@else
<x-icons.chevron-right class="w-4 h-4 text-gray-400" />
@endif
</button>
<x-icons.folder class="w-5 h-5 mr-2 text-yellow-500" />
<span class="cursor-pointer">{{ $folder->name }}</span>
</div>
<span class="text-sm text-gray-500">
{{ $folder->documents_count }}
</span>
</div>
@if(in_array($folder->id, $expandedFolders))
<ul class="mt-2 space-y-2">
@foreach($folder->children as $child)
<x-folder-item
:folder="$child"
:selectedFolderId="$selectedFolderId"
:expandedFolders="$expandedFolders"
:level="$level + 1"
wire:key="folder-{{ $child->id }}"
/>
@endforeach
</ul>
@endif
</li>

View File

@@ -0,0 +1,94 @@
@props(['icon' => ''])
@if($icon === 'dashboard')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
@elseif($icon === 'folder')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
</svg>
@elseif($icon === 'document')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
@elseif($icon === 'search')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
@elseif($icon === 'chevron-down')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
@elseif($icon === 'user')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
@elseif($icon === 'logout')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
@elseif($icon === 'eye')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
@elseif($icon === 'download')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
@elseif($icon === 'storage')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" />
</svg>
@elseif($icon === 'arrow-up')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18" />
</svg>
@elseif($icon === 'clock')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
@elseif($icon === 'trash')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
@elseif($icon === 'edit')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
</svg>
@elseif($icon === 'check')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
@elseif($icon === 'x')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
@elseif($icon === 'plus')
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
@else
<!-- Icono por defecto (question mark circle) -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
@endif

View File

@@ -0,0 +1,4 @@
<!-- resources/views/components/icons/upload.blade.php -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" {{ $attributes }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
</svg>

After

Width:  |  Height:  |  Size: 322 B

View File

@@ -0,0 +1,5 @@
<x-layouts.app.sidebar :title="$title ?? null">
<flux:main>
{{ $slot }}
</flux:main>
</x-layouts.app.sidebar>

View File

@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-white dark:bg-zinc-800">
<flux:header container class="border-b border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />
<a href="{{ route('dashboard') }}" class="ms-2 me-5 flex items-center space-x-2 rtl:space-x-reverse lg:ms-0" wire:navigate>
<x-app-logo />
</a>
<flux:navbar class="-mb-px max-lg:hidden">
<flux:navbar.item icon="layout-grid" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>
{{ __('Dashboard') }}
</flux:navbar.item>
</flux:navbar>
<flux:spacer />
<flux:navbar class="me-1.5 space-x-0.5 rtl:space-x-reverse py-0!">
<flux:tooltip :content="__('Search')" position="bottom">
<flux:navbar.item class="!h-10 [&>div>svg]:size-5" icon="magnifying-glass" href="#" :label="__('Search')" />
</flux:tooltip>
<flux:tooltip :content="__('Repository')" position="bottom">
<flux:navbar.item
class="h-10 max-lg:hidden [&>div>svg]:size-5"
icon="folder-git-2"
href="https://github.com/laravel/livewire-starter-kit"
target="_blank"
:label="__('Repository')"
/>
</flux:tooltip>
<flux:tooltip :content="__('Documentation')" position="bottom">
<flux:navbar.item
class="h-10 max-lg:hidden [&>div>svg]:size-5"
icon="book-open-text"
href="https://laravel.com/docs/starter-kits"
target="_blank"
label="Documentation"
/>
</flux:tooltip>
</flux:navbar>
<!-- Desktop User Menu -->
<flux:dropdown position="top" align="end">
<flux:profile
class="cursor-pointer"
:initials="auth()->user()->initials()"
/>
<flux:menu>
<flux:menu.radio.group>
<div class="p-0 text-sm font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
<span
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
>
{{ auth()->user()->initials() }}
</span>
</span>
<div class="grid flex-1 text-start text-sm leading-tight">
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
</div>
</div>
</div>
</flux:menu.radio.group>
<flux:menu.separator />
<flux:menu.radio.group>
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
</flux:menu.radio.group>
<flux:menu.separator />
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
{{ __('Log Out') }}
</flux:menu.item>
</form>
</flux:menu>
</flux:dropdown>
</flux:header>
<!-- Mobile Menu -->
<flux:sidebar stashable sticky class="lg:hidden border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
<a href="{{ route('dashboard') }}" class="ms-1 flex items-center space-x-2 rtl:space-x-reverse" wire:navigate>
<x-app-logo />
</a>
<flux:navlist variant="outline">
<flux:navlist.group :heading="__('Platform')">
<flux:navlist.item icon="layout-grid" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>
{{ __('Dashboard') }}
</flux:navlist.item>
</flux:navlist.group>
</flux:navlist>
<flux:spacer />
<flux:navlist variant="outline">
<flux:navlist.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
{{ __('Repository') }}
</flux:navlist.item>
<flux:navlist.item icon="book-open-text" href="https://laravel.com/docs/starter-kits" target="_blank">
{{ __('Documentation') }}
</flux:navlist.item>
</flux:navlist>
</flux:sidebar>
{{ $slot }}
@fluxScripts
</body>
</html>

View File

@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-white dark:bg-zinc-800">
<flux:sidebar sticky stashable class="border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
<a href="{{ route('dashboard') }}" class="me-5 flex items-center space-x-2 rtl:space-x-reverse" wire:navigate>
<x-app-logo />
</a>
<flux:navlist variant="outline">
<flux:navlist.group :heading="__('Platform')" class="grid">
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
</flux:navlist.group>
</flux:navlist>
<flux:spacer />
<flux:navlist variant="outline">
<flux:navlist.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
{{ __('Repository') }}
</flux:navlist.item>
<flux:navlist.item icon="book-open-text" href="https://laravel.com/docs/starter-kits" target="_blank">
{{ __('Documentation') }}
</flux:navlist.item>
</flux:navlist>
<!-- Desktop User Menu -->
<flux:dropdown position="bottom" align="start">
<flux:profile
:name="auth()->user()->name"
:initials="auth()->user()->initials()"
icon-trailing="chevrons-up-down"
/>
<flux:menu class="w-[220px]">
<flux:menu.radio.group>
<div class="p-0 text-sm font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
<span
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
>
{{ auth()->user()->initials() }}
</span>
</span>
<div class="grid flex-1 text-start text-sm leading-tight">
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
</div>
</div>
</div>
</flux:menu.radio.group>
<flux:menu.separator />
<flux:menu.radio.group>
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
</flux:menu.radio.group>
<flux:menu.separator />
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
{{ __('Log Out') }}
</flux:menu.item>
</form>
</flux:menu>
</flux:dropdown>
</flux:sidebar>
<!-- Mobile User Menu -->
<flux:header class="lg:hidden">
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />
<flux:spacer />
<flux:dropdown position="top" align="end">
<flux:profile
:initials="auth()->user()->initials()"
icon-trailing="chevron-down"
/>
<flux:menu>
<flux:menu.radio.group>
<div class="p-0 text-sm font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
<span
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
>
{{ auth()->user()->initials() }}
</span>
</span>
<div class="grid flex-1 text-start text-sm leading-tight">
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
</div>
</div>
</div>
</flux:menu.radio.group>
<flux:menu.separator />
<flux:menu.radio.group>
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
</flux:menu.radio.group>
<flux:menu.separator />
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
{{ __('Log Out') }}
</flux:menu.item>
</form>
</flux:menu>
</flux:dropdown>
</flux:header>
{{ $slot }}
@fluxScripts
</body>
</html>

View File

@@ -0,0 +1,3 @@
<x-layouts.auth.simple :title="$title ?? null">
{{ $slot }}
</x-layouts.auth.simple>

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-neutral-100 antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
<div class="bg-muted flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
<div class="flex w-full max-w-md flex-col gap-6">
<a href="{{ route('home') }}" class="flex flex-col items-center gap-2 font-medium" wire:navigate>
<span class="flex h-9 w-9 items-center justify-center rounded-md">
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
</span>
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
</a>
<div class="flex flex-col gap-6">
<div class="rounded-xl border bg-white dark:bg-stone-950 dark:border-stone-800 text-stone-800 shadow-xs">
<div class="px-10 py-8">{{ $slot }}</div>
</div>
</div>
</div>
</div>
@fluxScripts
</body>
</html>

View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-white antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
<div class="bg-background flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
<div class="flex w-full max-w-sm flex-col gap-2">
<a href="{{ route('home') }}" class="flex flex-col items-center gap-2 font-medium" wire:navigate>
<span class="flex h-9 w-9 mb-1 items-center justify-center rounded-md">
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
</span>
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
</a>
<div class="flex flex-col gap-6">
{{ $slot }}
</div>
</div>
</div>
@fluxScripts
</body>
</html>

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-white antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
<div class="relative grid h-dvh flex-col items-center justify-center px-8 sm:px-0 lg:max-w-none lg:grid-cols-2 lg:px-0">
<div class="bg-muted relative hidden h-full flex-col p-10 text-white lg:flex dark:border-e dark:border-neutral-800">
<div class="absolute inset-0 bg-neutral-900"></div>
<a href="{{ route('home') }}" class="relative z-20 flex items-center text-lg font-medium" wire:navigate>
<span class="flex h-10 w-10 items-center justify-center rounded-md">
<x-app-logo-icon class="me-2 h-7 fill-current text-white" />
</span>
{{ config('app.name', 'Laravel') }}
</a>
@php
[$message, $author] = str(Illuminate\Foundation\Inspiring::quotes()->random())->explode('-');
@endphp
<div class="relative z-20 mt-auto">
<blockquote class="space-y-2">
<flux:heading size="lg">&ldquo;{{ trim($message) }}&rdquo;</flux:heading>
<footer><flux:heading>{{ trim($author) }}</flux:heading></footer>
</blockquote>
</div>
</div>
<div class="w-full lg:p-8">
<div class="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<a href="{{ route('home') }}" class="z-20 flex flex-col items-center gap-2 font-medium lg:hidden" wire:navigate>
<span class="flex h-9 w-9 items-center justify-center rounded-md">
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
</span>
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
</a>
{{ $slot }}
</div>
</div>
</div>
@fluxScripts
</body>
</html>

View File

@@ -0,0 +1,40 @@
@props([
'options' => [],
'selected' => [],
'name' => 'multiselect',
'id' => 'multiselect-' . Str::random(5),
'wireModel' => null // Nuevo prop para el modelo Livewire
])
<div
x-data="{
open: false,
selected: @if($wireModel) @entangle($wireModel) @else {{ json_encode($selected) }} @endif
}"
class="relative"
<div
@click="open = !open"
class="cursor-pointer p-2 border rounded-lg flex items-center justify-between"
>
<span x-text="selected.length ? selected.join(', ') : 'Seleccione opciones'"></span>
<x-icons icon="chevron-down" class="w-4 h-4 ml-2" />
</div>
<div
x-show="open"
@click.away="open = false"
class="absolute z-50 w-full mt-1 bg-white border rounded-lg shadow-lg max-h-60 overflow-auto"
>
<template x-for="(option, index) in {{ json_encode($options) }}">
<label class="flex items-center px-4 py-2 hover:bg-gray-100">
<input
type="checkbox"
x-model="selected"
:value="option.value"
class="rounded border-gray-300 text-blue-600 shadow-sm focus:ring-blue-500"
>
<span x-text="option.label" class="ml-2"></span>
</label>
</template>
</div>
</div>

View File

@@ -0,0 +1,9 @@
@props(['href', 'active' => false])
<a href="{{ $href }}" {{ $attributes->class([
'flex items-center px-4 py-2 text-sm transition-colors',
'bg-gray-900 text-white' => $active,
'text-gray-300 hover:bg-gray-700 hover:text-white' => !$active
]) }}>
{{ $slot }}
</a>

View File

@@ -0,0 +1,12 @@
@props([
'id' => uniqid(),
])
<svg {{ $attributes }} fill="none">
<defs>
<pattern id="pattern-{{ $id }}" x="0" y="0" width="8" height="8" patternUnits="userSpaceOnUse">
<path d="M-1 5L5 -1M3 9L8.5 3.5" stroke-width="0.5"></path>
</pattern>
</defs>
<rect stroke="none" fill="url(#pattern-{{ $id }})" width="100%" height="100%"></rect>
</svg>

View File

@@ -0,0 +1,6 @@
<!-- resources/views/components/select.blade.php -->
@props(['disabled' => false])
<select {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'rounded-md shadow-sm border-gray-300 focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50']) !!}>
{{ $slot }}
</select>

View File

@@ -0,0 +1,20 @@
<div class="flex items-start max-md:flex-col">
<div class="me-10 w-full pb-4 md:w-[220px]">
<flux:navlist>
<flux:navlist.item :href="route('settings.profile')" wire:navigate>{{ __('Profile') }}</flux:navlist.item>
<flux:navlist.item :href="route('settings.password')" wire:navigate>{{ __('Password') }}</flux:navlist.item>
<flux:navlist.item :href="route('settings.appearance')" wire:navigate>{{ __('Appearance') }}</flux:navlist.item>
</flux:navlist>
</div>
<flux:separator class="md:hidden" />
<div class="flex-1 self-stretch max-md:pt-6">
<flux:heading>{{ $heading ?? '' }}</flux:heading>
<flux:subheading>{{ $subheading ?? '' }}</flux:subheading>
<div class="mt-5 w-full max-w-lg">
{{ $slot }}
</div>
</div>
</div>

View File

@@ -0,0 +1,30 @@
@props([
'title',
'value',
'icon', // ← Añade esta línea
'color',
'trend' => null, // Valor por defecto: null
'trendColor' => 'text-gray-500' // Color por defecto
])
<div class="bg-white p-6 rounded-lg shadow">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-500">{{ $title }}</p>
<p class="text-3xl font-bold">{{ $value }}</p>
</div>
<div class="{{ $color }} p-3 rounded-full">
@if($icon === 'folder')
<x-icons icon="folder" class="w-8 h-8 text-white" />
@elseif($icon === 'document')
<x-icons icon = "document" class="w-8 h-8 text-white" />
@endif
</div>
</div>
<div class="mt-4">
<span class="text-sm {{ $trendColor }}">
<x-icons icon="arrow-up" class="w-4 h-4 inline" /> {{ $trend }}%
</span>
<span class="text-sm text-gray-500">desde el último mes</span>
</div>
</div>

View File

@@ -0,0 +1,14 @@
@props(['status'])
@php
$colors = [
'pending' => 'bg-yellow-100 text-yellow-800',
'approved' => 'bg-green-100 text-green-800',
'rejected' => 'bg-red-100 text-red-800',
'in_review' => 'bg-blue-100 text-blue-800'
];
@endphp
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium {{ $colors[$status] }}">
{{ strtoupper($status) }}
</span>

View File

@@ -0,0 +1,4 @@
<!-- resources/views/components/textarea.blade.php -->
@props(['disabled' => false])
<textarea {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'rounded-md shadow-sm border-gray-300 focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50']) !!}>{{ $slot }}</textarea>

View File

@@ -0,0 +1,62 @@
<!-- resources/views/components/toolbar.blade.php -->
<div class="flex items-center justify-between mb-4 space-x-4">
<!-- Grupo izquierdo: Acciones principales -->
<div class="flex items-center space-x-2">
<!-- Crear nueva carpeta -->
<button wire:click="$emit('openCreateFolderModal')"
class="px-3 py-2 text-sm text-white bg-blue-600 rounded-lg hover:bg-blue-700">
<x-icons icon="folder-add" class="w-5 h-5 mr-1 inline" />
Nueva Carpeta
</button>
<!-- Subir archivos -->
<div x-data="{ isUploading: false }"
x-on:livewire-upload-start="isUploading = true"
x-on:livewire-upload-finish="isUploading = false"
x-on:livewire-upload-error="isUploading = false">
<button @click="document.getElementById('file-input').click()"
class="px-3 py-2 text-sm text-white bg-green-600 rounded-lg hover:bg-green-700"
:disabled="isUploading">
<x-icons icon="upload" class="w-5 h-5 mr-1 inline" />
<span x-text="isUploading ? 'Subiendo...' : 'Subir Archivos'"></span>
</button>
<input type="file"
id="file-input"
wire:model="files"
multiple
class="hidden"
@change="$wire.uploadFiles()">
</div>
</div>
<!-- Grupo derecho: Acciones adicionales -->
<div class="flex items-center space-x-2">
<!-- Menú desplegable con más opciones -->
<div class="relative" x-data="{ open: false }">
<button @click="open = !open"
class="p-2 text-gray-600 hover:bg-gray-100 rounded-lg">
<x-icons icon="dots-vertical" class="w-5 h-5" />
</button>
<div x-show="open"
@click.away="open = false"
class="absolute right-0 z-10 w-48 bg-white rounded-lg shadow-lg">
<div class="p-2 space-y-1">
<button wire:click="$emit('openCreateSubfolderModal')"
class="flex items-center w-full px-2 py-1 text-sm hover:bg-gray-100">
<x-icons icon="folder-plus" class="w-4 h-4 mr-2" />
Nueva Subcarpeta
</button>
<button wire:click="$emit('openMultiUploadModal')"
class="flex items-center w-full px-2 py-1 text-sm hover:bg-gray-100">
<x-icons icon="upload-multiple" class="w-4 h-4 mr-2" />
Subida Masiva
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Modal para crear carpeta -->
@livewire('folder.create-modal')