Files
dockersyshome/resources/views/news-show.blade.php
T
marco 38295e7e88 feat(cms): implement complete SysSiteCMS content management system
Initial implementation of the HomeSysPanel CMS built with Laravel 13.0.
Includes complete admin panel, content management, user authentication,
modular architecture for products/services/chatbot, and marketing tools.

Key features:
- User authentication with email verification and password reset
- Role-based access control (Admin/User with granular permissions)
- Content management (pages, news, FAQ, downloads, galleries, banners)
- Contact management system with subjects and responses
- Marketing tools (email campaigns, visitor analytics, social sharing)
- Modular architecture (Products, Services, Chatbot modules)
- AI Chatbot integration with OpenRouter.ai and LlamaCpp support
- Visitor tracking with geolocation
- SEO optimization with meta tags and Open Graph
- Responsive design with Bootstrap 5
- Dark mode support
- Maintenance mode
- Feature request system
2026-09-07 19:06:53 -03:00

162 lines
7.2 KiB
PHP
Executable File

@extends('layouts.app')
@section('title', ($news->seo_title ?: $news->title) . \App\Models\Setting::get('seo_title_suffix', ' - SysSiteCMS'))
@section('meta_description', $news->seo_description ?: Str::limit($news->summary ?? $news->title, 160))
@section('meta_keywords', $news->seo_keywords)
@section('og_title', $news->title)
@section('og_description', Str::limit($news->summary ?? $news->title, 200))
@section('og_image', $news->featured_image ? asset('storage/' . $news->featured_image) : '')
@section('content')
<div class="container py-5">
<article>
<!-- Header -->
<div class="text-center mb-5">
<h1 class="display-5 fw-bold text-primary">{{ $news->title }}</h1>
<div class="d-flex justify-content-center gap-4 text-muted mt-3">
@if($news->author)
<span><i class="bi bi-person me-1"></i> {{ $news->author }}</span>
@endif
<span><i class="bi bi-calendar me-1"></i> {{ ($news->published_at ?? $news->created_at)->format('d/m/Y H:i') }}</span>
</div>
</div>
<!-- Featured Image -->
@if($news->featured_image)
<div class="text-center mb-5">
<img src="{{ asset('storage/' . $news->featured_image) }}" alt="{{ $news->title }}" class="img-fluid rounded shadow-sm" style="max-height: 500px; object-fit: cover;">
</div>
@endif
<!-- Summary -->
@if($news->summary)
<div class="alert alert-light border-start border-primary border-4 ps-4 mb-4">
<p class="lead mb-0">{{ $news->summary }}</p>
</div>
@endif
<!-- Content -->
@if($news->content)
<div class="mb-5" style="line-height: 1.8; font-size: 1.1rem;">
{!! nl2br(e($news->content)) !!}
</div>
@endif
<!-- Additional Images Gallery -->
@if($news->images->count() > 0)
<div class="mb-5">
<h3 class="fw-bold mb-4"><i class="bi bi-images me-2 text-primary"></i> Galeria de Imagens</h3>
<div class="row g-3">
@foreach($news->images as $index => $image)
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="card h-100 border-0 shadow-sm overflow-hidden" style="cursor: pointer;" onclick="openCarousel({{ $index }})">
<img src="{{ asset('storage/' . $image->file_path) }}" class="card-img-top" alt="{{ $image->description }}" style="height: 160px; object-fit: cover; transition: transform 0.3s;">
@if($image->description)
<div class="card-body p-2 text-center bg-light">
<small class="text-muted">{{ $image->description }}</small>
</div>
@endif
</div>
</div>
@endforeach
</div>
</div>
@endif
</article>
<hr class="my-5">
<div class="d-flex justify-content-between align-items-center">
<a href="{{ route('news.index') }}" class="btn btn-outline-primary px-4 rounded-pill fw-bold">
<i class="bi bi-arrow-left me-2"></i> Todas as Notícias
</a>
<a href="{{ route('index') }}" class="btn btn-outline-secondary px-4 rounded-pill">
<i class="bi bi-house me-2"></i> Início
</a>
</div>
</div>
<!-- Carousel Modal for Additional Images -->
@if($news->images->count() > 0)
<div class="modal fade" id="newsCarouselModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-centered">
<div class="modal-content bg-dark border-0">
<div class="modal-header border-0 pb-0">
<h5 class="modal-title text-white" id="carouselImageTitle"></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Fechar"></button>
</div>
<div class="modal-body p-0">
<div id="newsCarousel" class="carousel slide" data-bs-ride="false">
<div class="carousel-inner">
@foreach($news->images as $index => $image)
<div class="carousel-item {{ $index === 0 ? 'active' : '' }}" data-index="{{ $index }}" data-title="{{ $image->description ?? '' }}">
<div class="d-flex align-items-center justify-content-center" style="min-height: 400px; max-height: 75vh;">
<img src="{{ asset('storage/' . $image->file_path) }}" class="d-block img-fluid" alt="{{ $image->description }}" style="max-height: 75vh; object-fit: contain;">
</div>
</div>
@endforeach
</div>
@if($news->images->count() > 1)
<button class="carousel-control-prev" type="button" data-bs-target="#newsCarousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Anterior</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#newsCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Próxima</span>
</button>
@endif
</div>
</div>
<div class="modal-footer border-0 pt-0 justify-content-center">
<span class="text-white-50" id="carouselCounter"></span>
</div>
</div>
</div>
</div>
@endif
@endsection
@push('css')
<style>
.card[style*="cursor: pointer"]:hover img {
transform: scale(1.05);
}
</style>
@endpush
@if($news->images->count() > 0)
@push('js')
<script>
const totalImages = {{ $news->images->count() }};
let carouselInstance = null;
function openCarousel(index) {
if (!carouselInstance) {
carouselInstance = new bootstrap.Carousel(document.getElementById('newsCarousel'));
}
carouselInstance.to(index);
updateCounter(index);
const item = document.querySelector(`#newsCarousel .carousel-item[data-index="${index}"]`);
if (item) {
document.getElementById('carouselImageTitle').textContent = item.dataset.title;
}
new bootstrap.Modal(document.getElementById('newsCarouselModal')).show();
}
function updateCounter(index) {
document.getElementById('carouselCounter').textContent = `${index + 1} / ${totalImages}`;
}
document.getElementById('newsCarousel').addEventListener('slid.bs.carousel', function (e) {
const activeItem = document.querySelector('#newsCarousel .carousel-item.active');
const index = parseInt(activeItem.dataset.index);
updateCounter(index);
document.getElementById('carouselImageTitle').textContent = activeItem.dataset.title;
});
</script>
@endpush
@endif