Initial commit: Lash Vanshy - Complete project with admin panel, gallery, products, and contact
This commit is contained in:
223
resources/views/admin/galeria/create.blade.php
Executable file
223
resources/views/admin/galeria/create.blade.php
Executable file
@@ -0,0 +1,223 @@
|
||||
@extends('admin.layouts.master')
|
||||
|
||||
@section('title', 'Nuevo Modelo - Lash Vanshy')
|
||||
|
||||
@section('page-title', 'Nuevo Modelo')
|
||||
|
||||
@section('content')
|
||||
<nav aria-label="breadcrumb" class="mb-4">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.galeria.index') }}">Galería</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Nuevo Modelo</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div class="card-admin">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-plus-circle me-2"></i>Nuevo Modelo
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{{ route('admin.galeria.store') }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="titulo" class="form-label">Titulo *</label>
|
||||
<input type="text"
|
||||
class="form-control @error('titulo') is-invalid @endif"
|
||||
id="titulo"
|
||||
name="titulo"
|
||||
value="{{ old('titulo') }}"
|
||||
placeholder="Ej: Extension de pestanas volumen russo"
|
||||
required>
|
||||
@error('titulo')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="tipo" class="form-label">Tipo *</label>
|
||||
<select class="form-select @error('tipo') is-invalid @endif"
|
||||
id="tipo"
|
||||
name="tipo"
|
||||
required
|
||||
onchange="toggleFileInputs()">
|
||||
<option value="">Selecciona el tipo</option>
|
||||
<option value="imagen" {{ old('tipo') === 'imagen' ? 'selected' : '' }}>Imagen</option>
|
||||
<option value="video" {{ old('tipo') === 'video' ? 'selected' : '' }}>Video</option>
|
||||
</select>
|
||||
@error('tipo')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="descripcion" class="form-label">Descripcion</label>
|
||||
<textarea class="form-control @error('descripcion') is-invalid @endif"
|
||||
id="descripcion"
|
||||
name="descripcion"
|
||||
rows="3"
|
||||
placeholder="Descripcion opcional del trabajo">{{ old('descripcion') }}</textarea>
|
||||
@error('descripcion')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="archivo" class="form-label">Archivo *</label>
|
||||
<input type="file"
|
||||
class="form-control @error('archivo') is-invalid @endif"
|
||||
id="archivo"
|
||||
name="archivo">
|
||||
<small class="text-muted" id="file-hint">Selecciona primero el tipo para ver los formatos validos</small>
|
||||
<div class="mt-2">
|
||||
<img id="file-preview" class="image-preview" style="max-width: 300px; display: none;">
|
||||
<video id="video-preview" class="video-preview" style="max-width: 300px; display: none;" controls></video>
|
||||
</div>
|
||||
@error('archivo')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-3" id="thumbnail-container" style="display: none;">
|
||||
<label for="thumbnail" class="form-label">Miniatura (Thumbnail)</label>
|
||||
<input type="file"
|
||||
class="form-control @error('thumbnail') is-invalid @endif"
|
||||
id="thumbnail"
|
||||
name="thumbnail"
|
||||
accept="image/*">
|
||||
<small class="text-muted">Imagen de previsualizacion para el video</small>
|
||||
<div class="mt-2">
|
||||
<img id="thumbnail-preview" class="image-preview" style="max-width: 150px; display: none;">
|
||||
</div>
|
||||
@error('thumbnail')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="orden" class="form-label">Orden</label>
|
||||
<input type="number"
|
||||
class="form-control"
|
||||
id="orden"
|
||||
name="orden"
|
||||
value="{{ old('orden', 0) }}"
|
||||
min="0"
|
||||
placeholder="0">
|
||||
<small class="text-muted">Orden de visualizacion (menor = primero)</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Estado</label>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
id="activo"
|
||||
name="activo"
|
||||
value="1"
|
||||
{{ old('activo', true) ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="activo">Activo (visible en web)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mt-4">
|
||||
<a href="{{ route('admin.galeria.index') }}" class="btn btn-secondary-admin">
|
||||
<i class="fas fa-arrow-left me-2"></i>Cancelar
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary-admin">
|
||||
<i class="fas fa-save me-2"></i>Guardar Modelo
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="card-admin">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-info-circle me-2"></i>Informacion
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted">
|
||||
Los modelos son trabajos realizados que se mostraran en la galeria publica del sitio web.
|
||||
</p>
|
||||
<ul class="text-muted">
|
||||
<li class="mb-2">Puedes subir imagenes o videos de tus trabajos</li>
|
||||
<li class="mb-2">Los videos necesitan una miniatura para mostrarse en la galeria</li>
|
||||
<li>Usa el campo "orden" para controlar el orden de visualizacion</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
function toggleFileInputs() {
|
||||
var tipo = document.getElementById('tipo').value;
|
||||
var archivo = document.getElementById('archivo');
|
||||
var fileHint = document.getElementById('file-hint');
|
||||
var thumbnailContainer = document.getElementById('thumbnail-container');
|
||||
|
||||
if (tipo === 'imagen') {
|
||||
archivo.accept = 'image/jpeg,image/png,image/gif,image/webp,image/svg+xml';
|
||||
fileHint.textContent = 'Formatos: JPG, PNG, GIF, WebP, SVG. Maximo: 100MB';
|
||||
thumbnailContainer.style.display = 'none';
|
||||
} else if (tipo === 'video') {
|
||||
archivo.accept = 'video/mp4,video/webm,video/ogg';
|
||||
fileHint.textContent = 'Formatos: MP4, WebM, OGG. Maximo: 100MB';
|
||||
thumbnailContainer.style.display = 'block';
|
||||
} else {
|
||||
archivo.accept = '';
|
||||
fileHint.textContent = 'Selecciona primero el tipo para ver los formatos validos';
|
||||
thumbnailContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('archivo').addEventListener('change', function(e) {
|
||||
var file = e.target.files[0];
|
||||
var imagePreview = document.getElementById('file-preview');
|
||||
var videoPreview = document.getElementById('video-preview');
|
||||
|
||||
if (!file) {
|
||||
imagePreview.style.display = 'none';
|
||||
videoPreview.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.type.startsWith('image/')) {
|
||||
imagePreview.src = URL.createObjectURL(file);
|
||||
imagePreview.style.display = 'block';
|
||||
videoPreview.style.display = 'none';
|
||||
} else if (file.type.startsWith('video/')) {
|
||||
videoPreview.src = URL.createObjectURL(file);
|
||||
videoPreview.style.display = 'block';
|
||||
imagePreview.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('thumbnail').addEventListener('change', function(e) {
|
||||
var file = e.target.files[0];
|
||||
var preview = document.getElementById('thumbnail-preview');
|
||||
|
||||
if (file && file.type.startsWith('image/')) {
|
||||
preview.src = URL.createObjectURL(file);
|
||||
preview.style.display = 'block';
|
||||
} else {
|
||||
preview.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
toggleFileInputs();
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@endsection
|
||||
307
resources/views/admin/galeria/edit.blade.php
Executable file
307
resources/views/admin/galeria/edit.blade.php
Executable file
@@ -0,0 +1,307 @@
|
||||
@extends('admin.layouts.master')
|
||||
|
||||
@section('title', 'Editar Modelo - Lash Vanshy')
|
||||
|
||||
@section('page-title', 'Editar Modelo')
|
||||
|
||||
@section('content')
|
||||
<!-- Breadcrumb -->
|
||||
<nav aria-label="breadcrumb" class="mb-4">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.galeria.index') }}">Galería</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Editar Modelo</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div class="card-admin">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-edit me-2"></i>Editar Modelo
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{{ route('admin.galeria.update', $galeria) }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="titulo" class="form-label">Título *</label>
|
||||
<input type="text"
|
||||
class="form-control @error('titulo') is-invalid @enderror"
|
||||
id="titulo"
|
||||
name="titulo"
|
||||
value="{{ old('titulo', $galeria->titulo) }}"
|
||||
placeholder="Ej: Extensión de pestañas volumen ruso"
|
||||
required>
|
||||
@error('titulo')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="tipo" class="form-label">Tipo *</label>
|
||||
<select class="form-select @error('tipo') is-invalid @enderror"
|
||||
id="tipo"
|
||||
name="tipo"
|
||||
required
|
||||
onchange="toggleFileInputs()">
|
||||
<option value="">Selecciona el tipo</option>
|
||||
<option value="imagen" {{ $galeria->tipo === 'imagen' ? 'selected' : '' }}>Imagen</option>
|
||||
<option value="video" {{ $galeria->tipo === 'video' ? 'selected' : '' }}>Video</option>
|
||||
</select>
|
||||
@error('tipo')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="descripcion" class="form-label">Descripción</label>
|
||||
<textarea class="form-control @error('descripcion') is-invalid @enderror"
|
||||
id="descripcion"
|
||||
name="descripcion"
|
||||
rows="3"
|
||||
placeholder="Descripción opcional del trabajo">{{ old('descripcion', $galeria->descripcion) }}</textarea>
|
||||
@error('descripcion')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<!-- Current File Info -->
|
||||
@if($galeria->tipo === 'imagen' && $galeria->archivo)
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Imagen Actual</label>
|
||||
<div class="mb-2">
|
||||
<img src="{{ asset('storage/' . $galeria->archivo) }}"
|
||||
alt="{{ $galeria->titulo }}"
|
||||
class="image-preview"
|
||||
style="max-height: 200px;">
|
||||
</div>
|
||||
<small class="text-muted">Deja este campo vacío para mantener la imagen actual</small>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($galeria->tipo === 'video')
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Video Actual</label>
|
||||
@if($galeria->archivo)
|
||||
<div class="mb-2">
|
||||
<video controls style="max-width: 100%; max-height: 200px; border-radius: 10px;">
|
||||
<source src="{{ asset('storage/' . $galeria->archivo) }}" type="video/mp4">
|
||||
Tu navegador no soporta videos.
|
||||
</video>
|
||||
</div>
|
||||
<small class="text-muted">Deja este campo vacío para mantener el video actual</small>
|
||||
@else
|
||||
<p class="text-muted">No hay video cargado</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Miniatura Actual</label>
|
||||
@if($galeria->thumbnail)
|
||||
<div class="mb-2">
|
||||
<img src="{{ asset('storage/' . $galeria->thumbnail) }}"
|
||||
alt="Thumbnail"
|
||||
class="image-preview"
|
||||
style="max-height: 150px;">
|
||||
</div>
|
||||
<small class="text-muted">Deja este campo vacío para mantener la miniatura actual</small>
|
||||
@else
|
||||
<p class="text-muted">No hay miniatura</p>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- New File Input -->
|
||||
@if($galeria->tipo === 'imagen')
|
||||
<div id="imagen-input" class="mb-3">
|
||||
<label for="archivo" class="form-label">Nueva Imagen</label>
|
||||
<input type="file"
|
||||
class="form-control @error('archivo') is-invalid @enderror"
|
||||
id="archivo"
|
||||
name="archivo"
|
||||
accept="image/*"
|
||||
onchange="previewImage(event, 'imagen-preview-edit')">
|
||||
<small class="text-muted">Formats: JPG, PNG, GIF. Max: 5MB</small>
|
||||
<div class="mt-2">
|
||||
<img id="imagen-preview-edit" class="image-preview" style="display: none;">
|
||||
</div>
|
||||
@error('archivo')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
@else
|
||||
<div id="imagen-input" class="mb-3" style="display: none;">
|
||||
<label for="archivo" class="form-label">Nueva Imagen</label>
|
||||
<input type="file"
|
||||
class="form-control @error('archivo') is-invalid @enderror"
|
||||
id="archivo"
|
||||
name="archivo"
|
||||
accept="image/*"
|
||||
onchange="previewImage(event, 'imagen-preview-edit')">
|
||||
<div class="mt-2">
|
||||
<img id="imagen-preview-edit" class="image-preview" style="display: none;">
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($galeria->tipo === 'video')
|
||||
<div id="video-inputs">
|
||||
<div class="mb-3">
|
||||
<label for="archivo_video" class="form-label">Nuevo Video</label>
|
||||
<input type="file"
|
||||
class="form-control @error('archivo') is-invalid @enderror"
|
||||
id="archivo_video"
|
||||
name="archivo"
|
||||
accept="video/*">
|
||||
<small class="text-muted">Formats: MP4, WebM. Max: 50MB</small>
|
||||
@error('archivo')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="thumbnail_video" class="form-label">Nueva Miniatura</label>
|
||||
<input type="file"
|
||||
class="form-control @error('thumbnail') is-invalid @enderror"
|
||||
id="thumbnail_video"
|
||||
name="thumbnail"
|
||||
accept="image/*"
|
||||
onchange="previewImage(event, 'thumbnail-preview-edit')">
|
||||
<div class="mt-2">
|
||||
<img id="thumbnail-preview-edit" class="image-preview" style="display: none;">
|
||||
</div>
|
||||
@error('thumbnail')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div id="video-inputs" style="display: none;">
|
||||
<div class="mb-3">
|
||||
<label for="archivo_video" class="form-label">Nuevo Video</label>
|
||||
<input type="file"
|
||||
class="form-control @error('archivo') is-invalid @enderror"
|
||||
id="archivo_video"
|
||||
name="archivo"
|
||||
accept="video/*">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="thumbnail_video" class="form-label">Nueva Miniatura</label>
|
||||
<input type="file"
|
||||
class="form-control @error('thumbnail') is-invalid @enderror"
|
||||
id="thumbnail_video"
|
||||
name="thumbnail"
|
||||
accept="image/*"
|
||||
onchange="previewImage(event, 'thumbnail-preview-edit')">
|
||||
<div class="mt-2">
|
||||
<img id="thumbnail-preview-edit" class="image-preview" style="display: none;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="orden" class="form-label">Orden</label>
|
||||
<input type="number"
|
||||
class="form-control"
|
||||
id="orden"
|
||||
name="orden"
|
||||
value="{{ old('orden', $galeria->orden) }}"
|
||||
min="0"
|
||||
placeholder="0">
|
||||
<small class="text-muted">Orden de visualización (menor = primero)</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Estado</label>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
id="activo"
|
||||
name="activo"
|
||||
value="1"
|
||||
{{ $galeria->activo ? 'checked' : '' }}>
|
||||
<label class="form-check-label" for="activo">Activo (visible en web)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mt-4">
|
||||
<a href="{{ route('admin.galeria.index') }}" class="btn btn-secondary-admin">
|
||||
<i class="fas fa-arrow-left me-2"></i>Cancelar
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary-admin">
|
||||
<i class="fas fa-save me-2"></i>Actualizar Modelo
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="card-admin">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-info-circle me-2"></i>Información
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted">
|
||||
Los modelos son trabajos realizados que se mostrarán en la galería pública del sitio web.
|
||||
</p>
|
||||
<ul class="text-muted">
|
||||
<li class="mb-2">Puedes subir imágenes o videos de tus trabajos</li>
|
||||
<li class="mb-2">Los videos necesitan una miniatura para mostrarse en la galería</li>
|
||||
<li>Usa el campo "orden" para controlar el orden de visualización</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
function toggleFileInputs() {
|
||||
const tipo = document.getElementById('tipo').value;
|
||||
const imagenInput = document.getElementById('imagen-input');
|
||||
const videoInputs = document.getElementById('video-inputs');
|
||||
|
||||
if (tipo === 'imagen') {
|
||||
imagenInput.style.display = 'block';
|
||||
videoInputs.style.display = 'none';
|
||||
} else if (tipo === 'video') {
|
||||
imagenInput.style.display = 'none';
|
||||
videoInputs.style.display = 'block';
|
||||
} else {
|
||||
imagenInput.style.display = 'none';
|
||||
videoInputs.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function previewImage(event, previewId) {
|
||||
const file = event.target.files[0];
|
||||
const preview = document.getElementById(previewId);
|
||||
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
preview.src = e.target.result;
|
||||
preview.style.display = 'block';
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
preview.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
toggleFileInputs();
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@endsection
|
||||
165
resources/views/admin/galeria/index.blade.php
Executable file
165
resources/views/admin/galeria/index.blade.php
Executable file
@@ -0,0 +1,165 @@
|
||||
@extends('admin.layouts.master')
|
||||
|
||||
@section('title', 'Galería - Lash Vanshy')
|
||||
|
||||
@section('page-title', 'Gestión de Galería')
|
||||
|
||||
@section('content')
|
||||
<!-- Header Actions -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h2 class="mb-0">Modelos / Galería</h2>
|
||||
<p class="text-muted mb-0">Administra las imágenes y videos de tus trabajos</p>
|
||||
</div>
|
||||
<a href="{{ route('admin.galeria.create') }}" class="btn btn-primary-admin">
|
||||
<i class="fas fa-plus me-2"></i>Nuevo Modelo
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Stats -->
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-sm-4">
|
||||
<div class="stat-card py-3">
|
||||
<div class="stat-info">
|
||||
<h3>{{ $galerias->total() }}</h3>
|
||||
<p>Total Modelos</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="stat-card py-3">
|
||||
<div class="stat-info">
|
||||
<h3>{{ $galerias->where('tipo', 'imagen')->count() }}</h3>
|
||||
<p>Imágenes</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="stat-card py-3">
|
||||
<div class="stat-info">
|
||||
<h3>{{ $galerias->where('tipo', 'video')->count() }}</h3>
|
||||
<p>Videos</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gallery Table -->
|
||||
<div class="card-admin">
|
||||
<div class="card-body">
|
||||
@if($galerias->isNotEmpty())
|
||||
<div class="table-responsive">
|
||||
<table class="table table-admin">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Orden</th>
|
||||
<th>Vista Previa</th>
|
||||
<th>Título</th>
|
||||
<th>Tipo</th>
|
||||
<th>Estado</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($galerias as $item)
|
||||
<tr>
|
||||
<td>
|
||||
<span class="badge-admin bg-info">{{ $item->orden }}</span>
|
||||
</td>
|
||||
<td>
|
||||
@if($item->tipo === 'video')
|
||||
@if($item->thumbnail)
|
||||
<img src="{{ asset('storage/' . $item->thumbnail) }}"
|
||||
alt="{{ $item->titulo }}"
|
||||
class="img-thumbnail"
|
||||
style="width: 60px; height: 40px; object-fit: cover;">
|
||||
@else
|
||||
<div class="placeholder-thumb">
|
||||
<i class="fas fa-video"></i>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
@if($item->archivo)
|
||||
<img src="{{ asset('storage/' . $item->archivo) }}"
|
||||
alt="{{ $item->titulo }}"
|
||||
class="img-thumbnail"
|
||||
style="width: 60px; height: 40px; object-fit: cover;">
|
||||
@else
|
||||
<div class="placeholder-thumb">
|
||||
<i class="fas fa-image"></i>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<strong>{{ $item->titulo }}</strong>
|
||||
@if($item->descripcion)
|
||||
<br><small class="text-muted">{{ Str::limit($item->descripcion, 40) }}</small>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge-admin {{ $item->tipo === 'video' ? 'bg-warning' : 'bg-info' }}">
|
||||
<i class="fas {{ $item->tipo === 'video' ? 'fa-video' : 'fa-image' }} me-1"></i>
|
||||
{{ ucfirst($item->tipo) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge-admin {{ $item->activo ? 'bg-success' : 'bg-danger' }}">
|
||||
{{ $item->activo ? 'Activo' : 'Inactivo' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="actions">
|
||||
<a href="{{ route('admin.galeria.edit', $item) }}"
|
||||
class="btn btn-sm btn-primary-admin"
|
||||
title="Editar">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<form action="{{ route('admin.galeria.destroy', $item) }}"
|
||||
method="POST"
|
||||
class="d-inline"
|
||||
onsubmit="return confirm('¿Estás seguro de que deseas eliminar este modelo?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-danger-admin" title="Eliminar">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="d-flex justify-content-center">
|
||||
{{ $galerias->links() }}
|
||||
</div>
|
||||
@else
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-images"></i>
|
||||
<h4>No hay modelos</h4>
|
||||
<p>Comienza agregando tu primer modelo a la galería</p>
|
||||
<a href="{{ route('admin.galeria.create') }}" class="btn btn-primary-admin mt-3">
|
||||
<i class="fas fa-plus me-2"></i>Agregar Modelo
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.placeholder-thumb {
|
||||
width: 60px;
|
||||
height: 40px;
|
||||
background: var(--secondary);
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user