307 lines
16 KiB
PHP
307 lines
16 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('content')
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">Promotions</h3>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-tool" data-toggle="dropdown">
|
|
<i class="fas fa-filter"></i> Filter
|
|
</button>
|
|
<div class="dropdown-menu dropdown-menu-right">
|
|
<a class="dropdown-item {{ request('status') == 'active' ? 'active' : '' }}"
|
|
href="{{ route('promotions.index', ['status' => 'active']) }}">
|
|
Active Promotions
|
|
</a>
|
|
<a class="dropdown-item {{ request('status') == 'inactive' ? 'active' : '' }}"
|
|
href="{{ route('promotions.index', ['status' => 'inactive']) }}">
|
|
Inactive Promotions
|
|
</a>
|
|
<a class="dropdown-item {{ !request('status') ? 'active' : '' }}"
|
|
href="{{ route('promotions.index') }}">
|
|
All Promotions
|
|
</a>
|
|
</div>
|
|
<a href="{{ route('promotions.create') }}" class="btn btn-primary ml-2">
|
|
<i class="fas fa-plus"></i> Add New Promotion
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
@include('components.alerts')
|
|
|
|
<div class="mb-3">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="input-group">
|
|
<input type="text"
|
|
class="form-control"
|
|
id="searchInput"
|
|
placeholder="Search promotions..."
|
|
value="{{ request('search') }}">
|
|
<div class="input-group-append">
|
|
<button class="btn btn-outline-secondary" type="button" id="searchButton">
|
|
<i class="fas fa-search"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="btn-group float-right">
|
|
<button type="button"
|
|
class="btn btn-outline-secondary view-switcher {{ session('view_type', 'grid') == 'grid' ? 'active' : '' }}"
|
|
data-view="grid">
|
|
<i class="fas fa-th-large"></i> Grid
|
|
</button>
|
|
<button type="button"
|
|
class="btn btn-outline-secondary view-switcher {{ session('view_type') == 'list' ? 'active' : '' }}"
|
|
data-view="list">
|
|
<i class="fas fa-list"></i> List
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="promotionsGrid" class="{{ session('view_type') == 'list' ? 'd-none' : '' }}">
|
|
<div class="row">
|
|
@forelse($promotions as $promotion)
|
|
<div class="col-md-4 col-lg-3 mb-4">
|
|
<div class="card h-100 promotion-card">
|
|
<div class="position-relative">
|
|
<img src="{{ $promotion['image_url'] }}"
|
|
class="card-img-top promotion-image"
|
|
alt="{{ $promotion['title'] }}"
|
|
loading="lazy">
|
|
<div class="promotion-overlay">
|
|
<span class="badge badge-{{ $promotion['is_active'] ? 'success' : 'danger' }}">
|
|
{{ $promotion['is_active'] ? 'Active' : 'Inactive' }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<h5 class="card-title text-truncate" title="{{ $promotion['title'] }}">
|
|
{{ $promotion['title'] }}
|
|
</h5>
|
|
<p class="card-text">{{ Str::limit($promotion['description'], 100) }}</p>
|
|
</div>
|
|
<div class="card-footer bg-transparent">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<small class="text-muted">
|
|
<i class="far fa-calendar-alt"></i>
|
|
{{ \Carbon\Carbon::parse($promotion['end_date'])->format('M d, Y') }}
|
|
</small>
|
|
<div class="btn-group">
|
|
<a href="{{ route('promotions.edit', $promotion['id']) }}"
|
|
class="btn btn-sm btn-info"
|
|
data-toggle="tooltip"
|
|
title="Edit Promotion">
|
|
<i class="fas fa-edit"></i>
|
|
</a>
|
|
<form action="{{ route('promotions.destroy', $promotion['id']) }}"
|
|
method="POST"
|
|
class="d-inline delete-form">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit"
|
|
class="btn btn-sm btn-danger"
|
|
data-toggle="tooltip"
|
|
title="Delete Promotion">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@empty
|
|
<div class="col-12">
|
|
<div class="alert alert-info">
|
|
<i class="fas fa-info-circle mr-2"></i>
|
|
No promotions found. Click the "Add New Promotion" button to create one.
|
|
</div>
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
</div>
|
|
|
|
<div id="promotionsList" class="{{ session('view_type') != 'list' ? 'd-none' : '' }}">
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Image</th>
|
|
<th>Title</th>
|
|
<th>Description</th>
|
|
<th>Status</th>
|
|
<th>Period</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@forelse($promotions as $promotion)
|
|
<tr>
|
|
<td class="text-center">
|
|
<img src="{{ $promotion['image_url'] }}"
|
|
alt="{{ $promotion['title'] }}"
|
|
class="img-thumbnail"
|
|
style="max-height: 50px;">
|
|
</td>
|
|
<td>{{ $promotion['title'] }}</td>
|
|
<td>{{ Str::limit($promotion['description'], 100) }}</td>
|
|
<td>
|
|
<span class="badge badge-{{ $promotion['is_active'] ? 'success' : 'danger' }}">
|
|
{{ $promotion['is_active'] ? 'Active' : 'Inactive' }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<small>
|
|
Start: {{ \Carbon\Carbon::parse($promotion['start_date'])->format('M d, Y') }}<br>
|
|
End: {{ \Carbon\Carbon::parse($promotion['end_date'])->format('M d, Y') }}
|
|
</small>
|
|
</td>
|
|
<td>
|
|
<div class="btn-group">
|
|
<a href="{{ route('promotions.edit', $promotion['id']) }}"
|
|
class="btn btn-sm btn-info"
|
|
data-toggle="tooltip"
|
|
title="Edit Promotion">
|
|
<i class="fas fa-edit"></i>
|
|
</a>
|
|
<form action="{{ route('promotions.destroy', $promotion['id']) }}"
|
|
method="POST"
|
|
class="d-inline delete-form">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit"
|
|
class="btn btn-sm btn-danger"
|
|
data-toggle="tooltip"
|
|
title="Delete Promotion">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="6" class="text-center">No promotions found</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-3">
|
|
{{ $promotions->links() }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@push('styles')
|
|
<style>
|
|
.promotion-card {
|
|
transition: transform 0.2s;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
.promotion-card:hover {
|
|
transform: translateY(-5px);
|
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
|
}
|
|
.promotion-image {
|
|
height: 200px;
|
|
object-fit: cover;
|
|
}
|
|
.promotion-overlay {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
}
|
|
.btn-group {
|
|
gap: 5px;
|
|
}
|
|
.view-switcher.active {
|
|
background-color: #007bff;
|
|
color: white;
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@push('scripts')
|
|
<script>
|
|
$(document).ready(function() {
|
|
// View switcher
|
|
$('.view-switcher').click(function() {
|
|
const view = $(this).data('view');
|
|
$('.view-switcher').removeClass('active');
|
|
$(this).addClass('active');
|
|
|
|
if (view === 'grid') {
|
|
$('#promotionsGrid').removeClass('d-none');
|
|
$('#promotionsList').addClass('d-none');
|
|
} else {
|
|
$('#promotionsGrid').addClass('d-none');
|
|
$('#promotionsList').removeClass('d-none');
|
|
}
|
|
|
|
// Save preference via AJAX
|
|
$.post('{{ route("preferences.store") }}', {
|
|
key: 'promotions_view_type',
|
|
value: view,
|
|
_token: '{{ csrf_token() }}'
|
|
});
|
|
});
|
|
|
|
// Search functionality
|
|
$('#searchButton').click(function() {
|
|
const searchTerm = $('#searchInput').val();
|
|
window.location.href = '{{ route("promotions.index") }}?search=' + encodeURIComponent(searchTerm);
|
|
});
|
|
|
|
$('#searchInput').keypress(function(e) {
|
|
if (e.which == 13) {
|
|
$('#searchButton').click();
|
|
}
|
|
});
|
|
|
|
// Delete confirmation
|
|
$('.delete-form').on('submit', function(e) {
|
|
e.preventDefault();
|
|
const title = $(this).closest('.promotion-card, tr').find('.card-title, td:eq(1)').text().trim();
|
|
|
|
if (confirm(`Are you sure you want to delete the promotion "${title}"? This action cannot be undone.`)) {
|
|
this.submit();
|
|
}
|
|
});
|
|
|
|
// Initialize tooltips
|
|
$('[data-toggle="tooltip"]').tooltip();
|
|
|
|
// Lazy load images
|
|
if ('loading' in HTMLImageElement.prototype) {
|
|
const images = document.querySelectorAll('img[loading="lazy"]');
|
|
images.forEach(img => {
|
|
img.src = img.src;
|
|
});
|
|
} else {
|
|
// Fallback for browsers that don't support lazy loading
|
|
const script = document.createElement('script');
|
|
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js';
|
|
document.body.appendChild(script);
|
|
script.onload = function() {
|
|
const observer = lozad();
|
|
observer.observe();
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
@endpush
|