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
This commit is contained in:
marco
2026-09-07 19:06:53 -03:00
commit 38295e7e88
279 changed files with 33691 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
@extends('layouts.admin')
@section('title', 'Novo Banner')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Cadastrar Banner</h1>
<a href="{{ route('admin.marketing.banners.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações do Banner</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.marketing.banners.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="row">
<div class="col-md-8">
<div class="form-group mb-3">
<label class="font-weight-bold">Título do Banner (Aparecerá no Carrossel)</label>
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror" value="{{ old('title') }}" required>
@error('title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Link (Opcional)</label>
<input type="url" name="link" class="form-control @error('link') is-invalid @enderror" value="{{ old('link') }}" placeholder="Ex: https://syspanel.com.br/promo">
@error('link') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Texto do Botão (Ex: Saiba Mais)</label>
<input type="text" name="button_text" class="form-control @error('button_text') is-invalid @enderror" value="{{ old('button_text') }}">
@error('button_text') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-3">
<label class="font-weight-bold">Imagem do Banner</label>
<input type="file" name="image" class="form-control-file @error('image') is-invalid @enderror" required>
<small class="text-muted d-block mt-2">Recomendado: 1920x600px para melhor visualização.</small>
@error('image') <div class="invalid-feedback d-block">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Ordem</label>
<input type="number" name="order" class="form-control @error('order') is-invalid @enderror" value="{{ old('order', 0) }}" required>
@error('order') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ old('active', '1') == '1' ? 'selected' : '' }}>Ativo</option>
<option value="0" {{ old('active') == '0' ? 'selected' : '' }}>Inativo</option>
</select>
</div>
</div>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Salvar Banner
</button>
</form>
</div>
</div>
@endsection
+87
View File
@@ -0,0 +1,87 @@
@extends('layouts.admin')
@section('title', 'Editar Banner')
@section('content')
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="{{ route('home') }}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.marketing.banners.index') }}">Marketing</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.marketing.banners.index') }}">Banners</a></li>
<li class="breadcrumb-item active">Editar Banner</li>
</ol>
</nav>
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar Banner: {{ $banner->title }}</h1>
<a href="{{ route('admin.marketing.banners.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações do Banner</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.marketing.banners.update', $banner) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="row">
<div class="col-md-8">
<div class="form-group mb-3">
<label class="font-weight-bold">Título do Banner (Aparecerá no Carrossel)</label>
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror" value="{{ old('title', $banner->title) }}" required>
@error('title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Link (Opcional)</label>
<input type="url" name="link" class="form-control @error('link') is-invalid @enderror" value="{{ old('link', $banner->link) }}" placeholder="Ex: https://syspanel.com.br/promo">
@error('link') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Texto do Botão (Ex: Saiba Mais)</label>
<input type="text" name="button_text" class="form-control @error('button_text') is-invalid @enderror" value="{{ old('button_text', $banner->button_text) }}">
@error('button_text') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-3">
<label class="font-weight-bold">Imagem do Banner</label>
@if($banner->image)
<div class="mb-2">
<img src="{{ asset('storage/' . $banner->image) }}" class="img-thumbnail" style="height: 100px;">
</div>
@endif
<input type="file" name="image" class="form-control-file @error('image') is-invalid @enderror">
<small class="text-muted d-block mt-2">Deixe em branco para manter a imagem atual.</small>
@error('image') <div class="invalid-feedback d-block">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Ordem</label>
<input type="number" name="order" class="form-control @error('order') is-invalid @enderror" value="{{ old('order', $banner->order) }}" required>
@error('order') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ old('active', $banner->active) == '1' ? 'selected' : '' }}>Ativo</option>
<option value="0" {{ old('active', $banner->active) == '0' ? 'selected' : '' }}>Inativo</option>
</select>
</div>
</div>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Salvar Alterações
</button>
</form>
</div>
</div>
@endsection
+80
View File
@@ -0,0 +1,80 @@
@extends('layouts.admin')
@section('title', 'Gerenciar Banners')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Gerenciar Banners (Destaques)</h1>
<a href="{{ route('admin.marketing.banners.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Novo Banner
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Banners Ativos e Inativos</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th width="50">Ordem</th>
<th width="200">Banner</th>
<th>Título</th>
<th>Botão / Link</th>
<th>Status</th>
<th width="120">Ações</th>
</tr>
</thead>
<tbody>
@forelse($banners as $banner)
<tr>
<td>{{ $banner->order }}</td>
<td>
<img src="{{ asset('storage/' . $banner->image) }}" class="img-fluid rounded" style="max-height: 60px;">
</td>
<td>{{ $banner->title }}</td>
<td>
@if($banner->button_text)
<span class="badge badge-primary">{{ $banner->button_text }}</span>
@endif
<br>
<small class="text-muted">{{ $banner->link ?: 'Sem link' }}</small>
</td>
<td>
<span class="badge badge-{{ $banner->active ? 'success' : 'secondary' }}">
{{ $banner->active ? 'Ativo' : 'Inativo' }}
</span>
</td>
<td>
<a href="{{ route('admin.marketing.banners.edit', $banner) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i>
</a>
<form action="{{ route('admin.marketing.banners.destroy', $banner) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Excluir este banner?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="text-center">Nenhum banner encontrado.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="mt-4">
{{ $banners->links() }}
</div>
</div>
</div>
@endsection
+67
View File
@@ -0,0 +1,67 @@
@extends('layouts.admin')
@section('title', 'Mensagens de Contato')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Contatos Recebidos</h1>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm">{{ session('success') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Mensagens</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Status</th>
<th>Data</th>
<th>Nome</th>
<th>Assunto</th>
<th>WhatsApp</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($contacts as $contact)
<tr class="{{ $contact->read ? 'text-muted' : 'font-weight-bold bg-light' }}">
<td class="text-center">
@if($contact->read)
<i class="bi bi-envelope-open text-secondary" title="Lida"></i>
@else
<i class="bi bi-envelope-fill text-primary" title="Nova!"></i>
@endif
</td>
<td>{{ $contact->created_at->format('d/m/Y H:i') }}</td>
<td>{{ $contact->name }}</td>
<td>{{ $contact->subject->name ?? 'N/A' }}</td>
<td>{{ $contact->whatsapp ?? '-' }}</td>
<td>
<a href="{{ route('admin.contacts.show', $contact) }}" class="btn btn-sm btn-info">
<i class="bi bi-eye"></i>
</a>
<form action="{{ route('admin.contacts.destroy', $contact) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Tem certeza que deseja excluir esta mensagem?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-4">
{{ $contacts->links() }}
</div>
</div>
</div>
@endsection
+152
View File
@@ -0,0 +1,152 @@
@extends('layouts.admin')
@section('title', 'Detalhes do Contato')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Mensagem de {{ $contact->name }}</h1>
<a href="{{ route('admin.contacts.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">
{{ session('success') }}
</div>
@endif
<div class="row">
<div class="col-lg-7">
<!-- Detalhes da Mensagem -->
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex justify-content-between align-items-center">
<h6 class="m-0 font-weight-bold text-primary">Conteúdo da Solicitação</h6>
<span class="text-muted small">{{ $contact->created_at->format('d/m/Y \à\s H:i') }}</span>
</div>
<div class="card-body">
<div class="row mb-4">
<div class="col-md-6">
<p class="mb-1 text-muted small text-uppercase fw-bold">Nome</p>
<p class="h5">{{ $contact->name }}</p>
</div>
<div class="col-md-6">
<p class="mb-1 text-muted small text-uppercase fw-bold">E-mail</p>
<p class="h5"><a href="mailto:{{ $contact->email }}">{{ $contact->email }}</a></p>
</div>
</div>
<div class="row mb-4">
<div class="col-md-4">
<p class="mb-1 text-muted small text-uppercase fw-bold">Empresa</p>
<p>{{ $contact->company ?? 'Não informada' }}</p>
</div>
<div class="col-md-4">
<p class="mb-1 text-muted small text-uppercase fw-bold">Site</p>
<p>
@if($contact->website)
<a href="{{ $contact->website }}" target="_blank">{{ $contact->website }}</a>
@else
Não informado
@endif
</p>
</div>
<div class="col-md-4">
<p class="mb-1 text-muted small text-uppercase fw-bold">WhatsApp</p>
<p>
@if($contact->whatsapp)
<a href="https://wa.me/{{ preg_replace('/[^0-9]/', '', $contact->whatsapp) }}" target="_blank" class="text-success fw-bold">
<i class="bi bi-whatsapp"></i> {{ $contact->whatsapp }}
</a>
@else
Não informado
@endif
</p>
</div>
</div>
<div class="row mb-4">
<div class="col-md-12">
<p class="mb-1 text-muted small text-uppercase fw-bold">Assunto</p>
<p class="badge badge-primary px-3 py-2" style="font-size: 1rem;">{{ $contact->subject->name ?? 'Geral' }}</p>
</div>
</div>
<hr>
<div class="row mt-4">
<div class="col-md-12">
<p class="mb-2 text-muted small text-uppercase fw-bold">Mensagem do Cliente</p>
<div class="bg-light p-4 rounded border" style="white-space: pre-wrap; min-height: 150px; font-size: 1.1rem;">{{ $contact->message }}</div>
</div>
</div>
</div>
</div>
<!-- Histórico de Respostas -->
<div class="card shadow mb-4">
<div class="card-header py-3 bg-light">
<h6 class="m-0 font-weight-bold text-dark"><i class="bi bi-clock-history me-1"></i> Histórico de Respostas</h6>
</div>
<div class="card-body">
@forelse($contact->responses as $response)
<div class="mb-4 pb-3 border-bottom">
<div class="d-flex justify-content-between mb-2">
<span class="font-weight-bold text-primary">{{ $response->user->name }}</span>
<span class="text-muted small">{{ $response->created_at->format('d/m/Y H:i') }}</span>
</div>
<div class="bg-white p-3 rounded border shadow-sm">
{{ $response->message }}
</div>
</div>
@empty
<p class="text-center text-muted py-4">Nenhuma resposta enviada ainda.</p>
@endforelse
</div>
</div>
</div>
<div class="col-lg-5">
<!-- Formulário de Resposta -->
<div class="card shadow mb-4 border-left-primary">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-reply me-1"></i> Enviar Resposta</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.contacts.reply', $contact) }}" method="POST">
@csrf
<div class="form-group mb-4">
<label class="font-weight-bold text-dark">Sua Mensagem</label>
<textarea name="message" class="form-control @error('message') is-invalid @enderror" rows="10" placeholder="Escreva aqui a resposta para o cliente..." required>{{ old('message') }}</textarea>
@error('message') <div class="invalid-feedback">{{ $message }}</div> @enderror
<small class="text-muted d-block mt-2">Esta mensagem será enviada para <strong>{{ $contact->email }}</strong>.</small>
</div>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-send me-1"></i> Enviar por E-mail
</button>
</form>
</div>
</div>
<!-- Ações Adicionais -->
<div class="card shadow mb-4">
<div class="card-body">
@if($contact->whatsapp)
<a href="https://wa.me/{{ preg_replace('/[^0-9]/', '', $contact->whatsapp) }}" target="_blank" class="btn btn-success btn-block mb-3 py-2 fw-bold">
<i class="bi bi-whatsapp me-1"></i> Chamar no WhatsApp
</a>
@endif
<form action="{{ route('admin.contacts.destroy', $contact) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-outline-danger btn-block" onclick="return confirm('Excluir esta mensagem permanentemente?')">
<i class="bi bi-trash me-1"></i> Excluir Registro do Sistema
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
+62
View File
@@ -0,0 +1,62 @@
@extends('layouts.admin')
@section('title', 'Novo Download')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Novo Download</h1>
<a href="{{ route('admin.downloads.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Upload de Arquivo</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.downloads.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">Título do Download</label>
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror" value="{{ old('title') }}" required placeholder="Ex: Driver Wi-Fi Notebook X">
@error('title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição</label>
<textarea name="description" class="form-control @error('description') is-invalid @enderror" rows="3">{{ old('description') }}</textarea>
@error('description') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Tipo de Arquivo</label>
<select name="file_type" class="form-control @error('file_type') is-invalid @enderror" required>
<option value="Driver">Driver</option>
<option value="Manual">Manual</option>
<option value="Software">Software</option>
<option value="Outro">Outro</option>
</select>
@error('file_type') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Arquivo (Máx 20MB)</label>
<input type="file" name="file" class="form-control-file @error('file') is-invalid @enderror" required>
@error('file') <div class="invalid-feedback d-block">{{ $message }}</div> @enderror
</div>
</div>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-upload me-1"></i> Fazer Upload e Salvar
</button>
</form>
</div>
</div>
@endsection
+73
View File
@@ -0,0 +1,73 @@
@extends('layouts.admin')
@section('title', 'Editar Download')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar Download</h1>
<a href="{{ route('admin.downloads.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações do Arquivo</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.downloads.update', $download) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="form-group mb-3">
<label class="font-weight-bold">Título do Download</label>
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror" value="{{ old('title', $download->title) }}" required>
@error('title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição</label>
<textarea name="description" class="form-control @error('description') is-invalid @enderror" rows="3">{{ old('description', $download->description) }}</textarea>
@error('description') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group mb-3">
<label class="font-weight-bold">Tipo de Arquivo</label>
<select name="file_type" class="form-control @error('file_type') is-invalid @enderror" required>
<option value="Driver" {{ $download->file_type == 'Driver' ? 'selected' : '' }}>Driver</option>
<option value="Manual" {{ $download->file_type == 'Manual' ? 'selected' : '' }}>Manual</option>
<option value="Software" {{ $download->file_type == 'Software' ? 'selected' : '' }}>Software</option>
<option value="Outro" {{ $download->file_type == 'Outro' ? 'selected' : '' }}>Outro</option>
</select>
@error('file_type') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-3">
<label class="font-weight-bold">Substituir Arquivo (Opcional)</label>
<input type="file" name="file" class="form-control-file @error('file') is-invalid @enderror">
<small class="text-muted d-block">Deixe em branco para manter o arquivo atual.</small>
@error('file') <div class="invalid-feedback d-block">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-3">
<label class="font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ $download->active ? 'selected' : '' }}>Ativo (Visível)</option>
<option value="0" {{ !$download->active ? 'selected' : '' }}>Inativo (Oculto)</option>
</select>
</div>
</div>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Salvar Alterações
</button>
</form>
</div>
</div>
@endsection
+66
View File
@@ -0,0 +1,66 @@
@extends('layouts.admin')
@section('title', 'Gerenciar Downloads')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Gerenciamento de Downloads</h1>
<a href="{{ route('admin.downloads.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Novo Download
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Arquivos Disponíveis</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Título</th>
<th>Tipo</th>
<th>Status</th>
<th>Baixado</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($downloads as $download)
<tr>
<td>{{ $download->title }}</td>
<td><span class="badge badge-secondary">{{ $download->file_type }}</span></td>
<td>
<span class="badge badge-{{ $download->active ? 'success' : 'secondary' }}">
{{ $download->active ? 'Ativo' : 'Inativo' }}
</span>
</td>
<td>{{ $download->download_count }} vezes</td>
<td>
<a href="{{ route('admin.downloads.edit', $download) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i>
</a>
<form action="{{ route('admin.downloads.destroy', $download) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Excluir este arquivo?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-4">
{{ $downloads->links() }}
</div>
</div>
</div>
@endsection
+240
View File
@@ -0,0 +1,240 @@
@extends('layouts.admin')
@section('title', 'Conheça o ERP Syspanel')
@section('content')
<div class="container-fluid">
<!-- Header de Propaganda -->
<div class="row mb-4">
<div class="col-12">
<div class="card bg-gradient-primary text-white shadow">
<div class="card-body p-5">
<div class="row align-items-center">
<div class="col-lg-8">
<h1 class="display-4 fw-bold">Potencialize sua Empresa com o ERP Syspanel</h1>
<p class="lead mb-4">A solução completa e inteligente para a gestão total do seu negócio. Do financeiro à Inteligência Artificial, tudo em um só lugar.</p>
<a href="https://syspanel.com.br" target="_blank" class="btn btn-light btn-lg px-5 py-3 rounded-pill fw-bold text-primary shadow-sm">
<i class="bi bi-rocket me-2"></i>Assine Agora o ERP Syspanel
</a>
</div>
<div class="col-lg-4 d-none d-lg-block text-center">
<i class="bi bi-graph-up opacity-25"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Título da Seção de Módulos -->
<div class="text-center mb-5">
<h2 class="h3 text-gray-800 font-weight-bold">Módulos Especializados para seu Crescimento</h2>
<div class="dropdown-divider w-25 mx-auto border-primary"></div>
</div>
<!-- Grid de Módulos -->
<div class="row g-4">
<!-- Módulo 1 -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Módulo ERP</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Financeiro</div>
<p class="text-muted small mt-2">Gestão de contas a pagar, receber e movimentações bancárias em tempo real.</p>
</div>
<div class="col-auto">
<i class="bi bi-cash-stack text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Módulo 2 -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">Módulo ERP</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">CRM</div>
<p class="text-muted small mt-2">Relacionamento completo: Leads, Oportunidades, Atividades e Pipelines de venda.</p>
</div>
<div class="col-auto">
<i class="bi bi-persons text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Módulo 3 -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Módulo ERP</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Gestão de Projetos</div>
<p class="text-muted small mt-2">Organize tarefas e prazos com metodologia Kanban e controle de produtividade.</p>
</div>
<div class="col-auto">
<i class="bi bi-list-task text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Módulo 4 -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Módulo ERP</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Estoque e Matérias-Primas</div>
<p class="text-muted small mt-2">Controle total de insumos, matérias-primas e armazéns com inteligência.</p>
</div>
<div class="col-auto">
<i class="bi bi-boxes text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Módulo IA -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-danger shadow h-100 py-2 bg-light">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">Módulo IA</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Agente de IA ERP</div>
<p class="text-muted small mt-2">Analise seus dados em tempo real com um agente inteligente exclusivo.</p>
</div>
<div class="col-auto">
<i class="bi bi-robot text-danger opacity-50"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Módulo 6 -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-secondary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-secondary text-uppercase mb-1">Módulo ERP</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Produção (PCP)</div>
<p class="text-muted small mt-2">Planejamento e controle rigoroso da produção e engenharia de produto (BOM).</p>
</div>
<div class="col-auto">
<i class="bi bi-gears text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Módulo 7 -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-dark shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-dark text-uppercase mb-1">Módulo ERP</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Veículos e Frotas</div>
<p class="text-muted small mt-2">Gestão de motoristas, ordens de serviço e manutenção de frotas da empresa.</p>
</div>
<div class="col-auto">
<i class="bi bi-truck text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Módulo 8 -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Módulo ERP</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Gestão da Qualidade</div>
<p class="text-muted small mt-2">Controle total de Manuais, Procedimentos e Formulários (SGQ).</p>
</div>
<div class="col-auto">
<i class="bi bi-check-circle text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Mais Módulos Listados -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Outros Módulos Inclusos</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<ul class="list-group list-group-flush">
<li class="list-group-item"><i class="bi bi-check-lg text-success me-2"></i>RH (Recursos Humanos)</li>
<li class="list-group-item"><i class="bi bi-check-lg text-success me-2"></i>Vendas ao Cliente</li>
<li class="list-group-item"><i class="bi bi-check-lg text-success me-2"></i>Gestão de Fornecedores</li>
</ul>
</div>
<div class="col-md-4">
<ul class="list-group list-group-flush">
<li class="list-group-item"><i class="bi bi-check-lg text-success me-2"></i>Transportadoras e Fretes</li>
<li class="list-group-item"><i class="bi bi-check-lg text-success me-2"></i>Service Tags</li>
<li class="list-group-item"><i class="bi bi-check-lg text-success me-2"></i>Gerência Comercial</li>
</ul>
</div>
<div class="col-md-4">
<ul class="list-group list-group-flush">
<li class="list-group-item"><i class="bi bi-star text-warning me-2"></i>Plano de Negócios IA</li>
<li class="list-group-item"><i class="bi bi-star text-warning me-2"></i>Assistente Local</li>
<li class="list-group-item"><i class="bi bi-check-lg text-success me-2"></i>Gestão de Organogramas</li>
</ul>
</div>
</div>
</div>
</div>
<!-- CTA Final -->
<div class="text-center py-5">
<h3 class="font-weight-bold text-gray-800">Pronto para transformar sua gestão?</h3>
<p class="lead text-muted mb-4">Junte-se a centenas de empresas que já utilizam o ecossistema Syspanel.</p>
<a href="https://syspanel.com.br" target="_blank" class="btn btn-primary btn-lg px-5 shadow-lg fw-bold">
Quero conhecer o ERP Syspanel agora!
</a>
<div class="mt-3">
<small class="text-muted">Acesse <a href="https://syspanel.com.br" target="_blank">syspanel.com.br</a> para mais informações.</small>
</div>
</div>
</div>
@endsection
@push('css')
<style>
.bg-gradient-primary {
background: linear-gradient(135deg, #4e73df 0%, #224abe 100%);
}
.hover-scale {
transition: transform 0.2s;
}
.hover-scale:hover {
transform: scale(1.02);
}
</style>
@endpush
+47
View File
@@ -0,0 +1,47 @@
@extends('layouts.admin')
@section('title', 'Nova Pergunta FAQ')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Nova Pergunta FAQ</h1>
<a href="{{ route('admin.faqs.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Criar Pergunta e Resposta</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.faqs.store') }}" method="POST">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">Pergunta</label>
<input type="text" name="question" class="form-control @error('question') is-invalid @enderror" value="{{ old('question') }}" required>
@error('question') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Resposta</label>
<textarea name="answer" class="form-control @error('answer') is-invalid @enderror" rows="5" required>{{ old('answer') }}</textarea>
@error('answer') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Ordem de Exibição</label>
<input type="number" name="order" class="form-control @error('order') is-invalid @enderror" value="{{ old('order', 0) }}" required>
<small class="text-muted">Números menores aparecem primeiro.</small>
@error('order') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Criar Pergunta
</button>
</form>
</div>
</div>
@endsection
+60
View File
@@ -0,0 +1,60 @@
@extends('layouts.admin')
@section('title', 'Editar FAQ')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar FAQ</h1>
<a href="{{ route('admin.faqs.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Editar Pergunta e Resposta</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.faqs.update', $faq) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group mb-3">
<label class="font-weight-bold">Pergunta</label>
<input type="text" name="question" class="form-control @error('question') is-invalid @enderror" value="{{ old('question', $faq->question) }}" required>
@error('question') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Resposta</label>
<textarea name="answer" class="form-control @error('answer') is-invalid @enderror" rows="5" required>{{ old('answer', $faq->answer) }}</textarea>
@error('answer') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Ordem de Exibição</label>
<input type="number" name="order" class="form-control @error('order') is-invalid @enderror" value="{{ old('order', $faq->order) }}" required>
@error('order') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ old('active', $faq->active) ? 'selected' : '' }}>Ativa</option>
<option value="0" {{ old('active', $faq->active) ? '' : 'selected' }}>Inativa</option>
</select>
</div>
</div>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Salvar Alterações
</button>
</form>
</div>
</div>
@endsection
+64
View File
@@ -0,0 +1,64 @@
@extends('layouts.admin')
@section('title', 'Gerenciar FAQ')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Perguntas Frequentes (FAQ)</h1>
<a href="{{ route('admin.faqs.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Nova Pergunta
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm">{{ session('success') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Perguntas</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Ordem</th>
<th>Pergunta</th>
<th>Status</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($faqs as $faq)
<tr>
<td>{{ $faq->order }}</td>
<td>{{ $faq->question }}</td>
<td>
<span class="badge badge-{{ $faq->active ? 'success' : 'secondary' }}">
{{ $faq->active ? 'Ativa' : 'Inativa' }}
</span>
</td>
<td>
<a href="{{ route('admin.faqs.edit', $faq) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i>
</a>
<form action="{{ route('admin.faqs.destroy', $faq) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Excluir esta pergunta?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-4">
{{ $faqs->links() }}
</div>
</div>
</div>
@endsection
+67
View File
@@ -0,0 +1,67 @@
@extends('layouts.admin')
@section('title', 'Nova Galeria')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Criar Galeria</h1>
<a href="{{ route('admin.galleries.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações Básicas</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.galleries.store') }}" method="POST">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">Categoria</label>
<select name="category_id" class="form-control">
<option value="">Sem categoria</option>
@foreach($categories as $category)
<option value="{{ $category->id }}" {{ old('category_id') == $category->id ? 'selected' : '' }}>{{ $category->name }}</option>
@endforeach
</select>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Título da Galeria</label>
<input type="text" name="title" id="title" class="form-control @error('title') is-invalid @enderror" value="{{ old('title') }}" required placeholder="Ex: Nossos Serviços, Evento 2024">
@error('title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Slug (URL)</label>
<input type="text" name="slug" id="slug" class="form-control @error('slug') is-invalid @enderror" value="{{ old('slug') }}" required>
@error('slug') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição (Opcional)</label>
<textarea name="description" class="form-control" rows="3">{{ old('description') }}</textarea>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Criar Galeria e Adicionar Fotos
</button>
</form>
</div>
</div>
@endsection
@push('js')
<script>
document.getElementById('title').addEventListener('keyup', function() {
let text = this.value.toLowerCase()
.normalize('NFD').replace(/[\u0300-\u036f]/g, "")
.replace(/[^\w ]+/g, '')
.replace(/ +/g, '-');
document.getElementById('slug').value = text;
});
</script>
@endpush
+124
View File
@@ -0,0 +1,124 @@
@extends('layouts.admin')
@section('title', 'Editar Galeria')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Gerenciar Galeria: {{ $gallery->title }}</h1>
<a href="{{ route('admin.galleries.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<div class="row">
<!-- Configurações da Galeria -->
<div class="col-lg-4">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Configurações</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.galleries.update', $gallery) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group mb-3">
<label class="small font-weight-bold">Categoria</label>
<select name="category_id" class="form-control">
<option value="">Sem categoria</option>
@foreach($categories as $category)
<option value="{{ $category->id }}" {{ $gallery->category_id == $category->id ? 'selected' : '' }}>{{ $category->name }}</option>
@endforeach
</select>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Título</label>
<input type="text" name="title" class="form-control" value="{{ $gallery->title }}" required>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">URL (Slug)</label>
<input type="text" name="slug" class="form-control" value="{{ $gallery->slug }}" required>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Descrição</label>
<textarea name="description" class="form-control" rows="3">{{ $gallery->description }}</textarea>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ $gallery->active ? 'selected' : '' }}>Ativa</option>
<option value="0" {{ !$gallery->active ? 'selected' : '' }}>Inativa</option>
</select>
</div>
<button type="submit" class="btn btn-primary btn-block">Salvar Alterações</button>
</form>
</div>
</div>
<!-- Upload de Imagens -->
<div class="card shadow mb-4">
<div class="card-header py-3 bg-light">
<h6 class="m-0 font-weight-bold text-dark">Adicionar Fotos</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.galleries.upload', $gallery) }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="form-group mb-3">
<label class="small font-weight-bold">Selecionar Imagens</label>
<input type="file" name="images[]" class="form-control-file" multiple accept="image/*" required>
<small class="text-muted">Selecione uma ou mais imagens (máx. 5MB cada).</small>
</div>
<button type="submit" class="btn btn-success btn-block">
<i class="bi bi-upload me-1"></i> Enviar Fotos
</button>
</form>
</div>
</div>
</div>
<!-- Lista de Imagens -->
<div class="col-lg-8">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Fotos na Galeria</h6>
</div>
<div class="card-body">
<div class="row">
@forelse($gallery->images as $img)
<div class="col-md-6 mb-4">
<div class="card h-100 border-0 shadow-sm overflow-hidden">
<img src="{{ asset('storage/' . $img->file_path) }}" class="card-img-top" style="height: 150px; object-fit: cover;">
<div class="card-body p-3">
<form action="{{ route('admin.galleries.image.update', $img) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group mb-2">
<input type="text" name="description" class="form-control form-control-sm" value="{{ $img->description }}" placeholder="Descrição da imagem">
</div>
<div class="d-flex gap-2">
<input type="number" name="order" class="form-control form-control-sm w-25" value="{{ $img->order }}" title="Ordem">
<button type="submit" class="btn btn-sm btn-primary flex-grow-1">Salvar</button>
</div>
</form>
<form action="{{ route('admin.galleries.image.delete', $img) }}" method="POST" class="mt-2">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-outline-danger btn-block" onclick="return confirm('Remover esta foto?')">Excluir</button>
</form>
</div>
</div>
</div>
@empty
<div class="col-12 text-center py-5">
<p class="text-muted">Nenhuma foto adicionada ainda.</p>
</div>
@endforelse
</div>
</div>
</div>
</div>
</div>
@endsection
+71
View File
@@ -0,0 +1,71 @@
@extends('layouts.admin')
@section('title', 'Gerenciar Galerias')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Galerias de Imagens</h1>
<a href="{{ route('admin.galleries.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Nova Galeria
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Galerias</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Título</th>
<th>Categoria</th>
<th>URL (Slug)</th>
<th>Imagens</th>
<th>Status</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($galleries as $gallery)
<tr>
<td>{{ $gallery->title }}</td>
<td>{{ $gallery->category?->name ?? '<span class="text-muted">—</span>' }}</td>
<td><code>/galeria/{{ $gallery->slug }}</code></td>
<td>{{ $gallery->images_count }} fotos</td>
<td>
<span class="badge badge-{{ $gallery->active ? 'success' : 'secondary' }}">
{{ $gallery->active ? 'Ativa' : 'Inativa' }}
</span>
</td>
<td>
<a href="{{ route('admin.galleries.edit', $gallery) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i> Gerenciar Fotos
</a>
<a href="{{ route('gallery.show', $gallery->slug) }}" target="_blank" class="btn btn-sm btn-info">
<i class="bi bi-eye"></i> Ver
</a>
<form action="{{ route('admin.galleries.destroy', $gallery) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Excluir esta galeria e TODAS as suas fotos?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-4">
{{ $galleries->links() }}
</div>
</div>
</div>
@endsection
+57
View File
@@ -0,0 +1,57 @@
@extends('layouts.admin')
@section('title', 'Nova Categoria de Galeria')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Criar Categoria</h1>
<a href="{{ route('admin.gallery-categories.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações da Categoria</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.gallery-categories.store') }}" method="POST">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">Nome da Categoria</label>
<input type="text" name="name" id="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name') }}" required placeholder="Ex: Eventos, Projetos, Portfólio">
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Slug (URL)</label>
<input type="text" name="slug" id="slug" class="form-control @error('slug') is-invalid @enderror" value="{{ old('slug') }}" required>
@error('slug') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição (Opcional)</label>
<textarea name="description" class="form-control" rows="3">{{ old('description') }}</textarea>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Criar Categoria
</button>
</form>
</div>
</div>
@endsection
@push('js')
<script>
document.getElementById('name').addEventListener('keyup', function() {
let text = this.value.toLowerCase()
.normalize('NFD').replace(/[\u0300-\u036f]/g, "")
.replace(/[^\w ]+/g, '')
.replace(/ +/g, '-');
document.getElementById('slug').value = text;
});
</script>
@endpush
+54
View File
@@ -0,0 +1,54 @@
@extends('layouts.admin')
@section('title', 'Editar Categoria de Galeria')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar Categoria: {{ $galleryCategory->name }}</h1>
<a href="{{ route('admin.gallery-categories.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações da Categoria</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.gallery-categories.update', $galleryCategory) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group mb-3">
<label class="font-weight-bold">Nome da Categoria</label>
<input type="text" name="name" id="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name', $galleryCategory->name) }}" required>
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Slug (URL)</label>
<input type="text" name="slug" id="slug" class="form-control @error('slug') is-invalid @enderror" value="{{ old('slug', $galleryCategory->slug) }}" required>
@error('slug') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição (Opcional)</label>
<textarea name="description" class="form-control" rows="3">{{ old('description', $galleryCategory->description) }}</textarea>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ $galleryCategory->active ? 'selected' : '' }}>Ativa</option>
<option value="0" {{ !$galleryCategory->active ? 'selected' : '' }}>Inativa</option>
</select>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Salvar Alterações
</button>
</form>
</div>
</div>
@endsection
+66
View File
@@ -0,0 +1,66 @@
@extends('layouts.admin')
@section('title', 'Categorias de Galerias')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Categorias de Galerias</h1>
<a href="{{ route('admin.gallery-categories.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Nova Categoria
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Categorias</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Nome</th>
<th>Slug</th>
<th>Galerias</th>
<th>Status</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($categories as $category)
<tr>
<td>{{ $category->name }}</td>
<td><code>{{ $category->slug }}</code></td>
<td>{{ $category->galleries_count }}</td>
<td>
<span class="badge badge-{{ $category->active ? 'success' : 'secondary' }}">
{{ $category->active ? 'Ativa' : 'Inativa' }}
</span>
</td>
<td>
<a href="{{ route('admin.gallery-categories.edit', $category) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i>
</a>
<form action="{{ route('admin.gallery-categories.destroy', $category) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Excluir esta categoria? As galerias associadas não serão excluídas.')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-4">
{{ $categories->links() }}
</div>
</div>
</div>
@endsection
+601
View File
@@ -0,0 +1,601 @@
@extends('layouts.admin')
@section('title', 'Manual de Uso')
@section('content')
<div class="container-fluid px-4">
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 text-gray-800"><i class="bi bi-book me-2"></i>Manual de Uso do Sistema</h1>
</div>
<!-- Table of Contents -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-list-ol me-2"></i>Sumário</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<ul class="list-unstyled">
<li class="mb-2"><a href="#acesso" class="text-primary">1. Acesso ao Painel</a></li>
<li class="mb-2"><a href="#dashboard" class="text-primary">2. Dashboard</a></li>
<li class="mb-2"><a href="#usuarios" class="text-primary">3. Gerenciamento de Usuários</a></li>
<li class="mb-2"><a href="#permissoes" class="text-primary">4. Permissões de Acesso</a></li>
<li class="mb-2"><a href="#contatos" class="text-primary">5. Mensagens de Contato</a></li>
<li class="mb-2"><a href="#assuntos" class="text-primary">6. Assuntos de Contato</a></li>
</ul>
</div>
<div class="col-md-4">
<ul class="list-unstyled">
<li class="mb-2"><a href="#servicos" class="text-primary">7. Serviços</a></li>
<li class="mb-2"><a href="#faq" class="text-primary">8. Perguntas Frequentes (FAQ)</a></li>
<li class="mb-2"><a href="#noticias" class="text-primary">9. Notícias</a></li>
<li class="mb-2"><a href="#downloads" class="text-primary">10. Central de Downloads</a></li>
<li class="mb-2"><a href="#produtos" class="text-primary">11. Produtos</a></li>
<li class="mb-2"><a href="#galerias" class="text-primary">12. Galerias de Imagens</a></li>
</ul>
</div>
<div class="col-md-4">
<ul class="list-unstyled">
<li class="mb-2"><a href="#paginas" class="text-primary">13. Páginas Institucionais</a></li>
<li class="mb-2"><a href="#marketing" class="text-primary">14. Marketing</a></li>
<li class="mb-2"><a href="#configuracoes" class="text-primary">15. Configurações do Sistema</a></li>
<li class="mb-2"><a href="#perfil" class="text-primary">16. Perfil e Preferências</a></li>
<li class="mb-2"><a href="#notificacoes" class="text-primary">17. Notificações</a></li>
<li class="mb-2"><a href="#dicas" class="text-primary">18. Dicas e Boas Práticas</a></li>
</ul>
</div>
</div>
</div>
</div>
<!-- Section 1: Acesso ao Painel -->
<div class="card shadow mb-4" id="acesso">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-lock me-2"></i>1. Acesso ao Painel Administrativo</h6>
</div>
<div class="card-body">
<p>Para acessar o painel administrativo do seu site:</p>
<ol>
<li>Acesse o endereço <code>http://seusite.com.br/login</code></li>
<li>Insira seu <strong>e-mail</strong> e <strong>senha</strong> cadastrados</li>
<li>Clique em <strong>"Entrar"</strong></li>
<li>Após o login, você será redirecionado para o Dashboard</li>
</ol>
<div class="alert alert-info">
<i class="bi bi-info-circle me-1"></i>
<strong>Primeiro acesso?</strong> Altere sua senha imediatamente em <strong>Configurações > Perfil</strong>.
</div>
</div>
</div>
<!-- Section 2: Dashboard -->
<div class="card shadow mb-4" id="dashboard">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-speedometer2 me-2"></i>2. Dashboard</h6>
</div>
<div class="card-body">
<p>O Dashboard é a página inicial do painel administrativo. Ele apresenta:</p>
<ul>
<li><strong>Métricas rápidas</strong>: Total de usuários, produtos, serviços, galerias, páginas e notícias</li>
<li><strong>Atalhos rápidos</strong>: Links para as funcionalidades mais utilizadas</li>
<li><strong>Sugestão de funcionalidades</strong>: Use o formulário "Sugerir Funcionalidade" para enviar solicitações ao suporte</li>
</ul>
</div>
</div>
<!-- Section 3: Usuários -->
<div class="card shadow mb-4" id="usuarios">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-people me-2"></i>3. Gerenciamento de Usuários</h6>
</div>
<div class="card-body">
<p><em>Disponível apenas para administradores.</em></p>
<p>No menu <strong>Usuários</strong>, você pode:</p>
<ul>
<li><strong>Listar</strong> todos os usuários cadastrados no sistema</li>
<li><strong>Criar</strong> novos usuários com tipo Admin ou Usuário comum</li>
<li><strong>Editar</strong> dados de usuários existentes (nome, e-mail, tipo, avatar)</li>
<li><strong>Excluir</strong> usuários (exceto o administrador principal)</li>
</ul>
<h6 class="mt-3"><i class="bi bi-tag me-1"></i>Tipos de Usuário</h6>
<div class="table-responsive">
<table class="table table-bordered table-sm">
<thead class="thead-light">
<tr>
<th>Tipo</th>
<th>Descrição</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="badge badge-primary">Admin</span></td>
<td>Acesso total ao painel, incluindo gerenciamento de usuários, tipos de usuário e todas as permissões</td>
</tr>
<tr>
<td><span class="badge badge-secondary">User</span></td>
<td>Acesso limitado baseado em permissões específicas atribuídas pelo administrador</td>
</tr>
</tbody>
</table>
</div>
<h6 class="mt-3">Tipos de Usuário Personalizados</h6>
<p>No menu <strong>Tipos de Usuário</strong>, você pode criar tipos personalizados com combinações específicas de permissões para diferentes perfis de acesso.</p>
</div>
</div>
<!-- Section 4: Permissões -->
<div class="card shadow mb-4" id="permissoes">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-shield-check me-2"></i>4. Permissões de Acesso</h6>
</div>
<div class="card-body">
<p>O sistema utiliza um modelo de permissões para controlar o acesso dos usuários. Ao editar um usuário, você pode atribuir permissões individuais:</p>
<div class="table-responsive">
<table class="table table-bordered table-sm">
<thead class="thead-light">
<tr>
<th>Permissão</th>
<th>Descrição</th>
<th>Seção no Painel</th>
</tr>
</thead>
<tbody>
<tr><td><code>pages</code></td><td>Gerenciar páginas institucionais</td><td>Páginas</td></tr>
<tr><td><code>news</code></td><td>Gerenciar notícias</td><td>Notícias</td></tr>
<tr><td><code>galleries</code></td><td>Gerenciar galerias e categorias</td><td>Galerias</td></tr>
<tr><td><code>products</code></td><td>Gerenciar produtos e categorias</td><td>Produtos</td></tr>
<tr><td><code>services</code></td><td>Gerenciar serviços</td><td>Serviços</td></tr>
<tr><td><code>contacts</code></td><td>Visualizar e responder mensagens de contato</td><td>Contatos</td></tr>
<tr><td><code>subjects</code></td><td>Gerenciar assuntos do formulário de contato</td><td>Assuntos</td></tr>
<tr><td><code>faqs</code></td><td>Gerenciar perguntas frequentes</td><td>FAQ</td></tr>
<tr><td><code>downloads</code></td><td>Gerenciar arquivos para download</td><td>Downloads</td></tr>
<tr><td><code>marketing</code></td><td>Acessar ferramentas de marketing, analytics e banners</td><td>Marketing</td></tr>
<tr><td><code>settings</code></td><td>Alterar configurações globais do site</td><td>Dados da Empresa</td></tr>
</tbody>
</table>
</div>
<div class="alert alert-warning">
<i class="bi bi-exclamation-triangle me-1"></i>
<strong>Atenção:</strong> Administradores possuem acesso total automaticamente, sem necessidade de permissões individuais.
</div>
</div>
</div>
<!-- Section 5: Contatos -->
<div class="card shadow mb-4" id="contatos">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-envelope me-2"></i>5. Mensagens de Contato</h6>
</div>
<div class="card-body">
<p>Todas as mensagens enviadas pelo formulário de contato do site são listadas no menu <strong>Contatos</strong>.</p>
<h6 class="mt-2">Funcionalidades:</h6>
<ul>
<li><strong>Visualizar</strong>: Clique em uma mensagem para ver os detalhes completos (nome, e-mail, assunto, mensagem)</li>
<li><strong>Responder</strong>: Digite sua resposta diretamente no painel. O cliente receberá um e-mail formatado com a resposta</li>
<li><strong>Excluir</strong>: Remova mensagens antigas ou irrelevantes</li>
</ul>
<div class="alert alert-info">
<i class="bi bi-lightbulb me-1"></i>
<strong>Dica:</strong> Configure os assuntos do formulário de contato no menu <strong>Assuntos</strong> para organizar melhor as mensagens recebidas (ex: Orçamento, Suporte, Comercial).
</div>
</div>
</div>
<!-- Section 6: Assuntos -->
<div class="card shadow mb-4" id="assuntos">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-tags me-2"></i>6. Assuntos de Contato</h6>
</div>
<div class="card-body">
<p>No menu <strong>Assuntos</strong>, você gerencia as opções de assunto que aparecem no formulário de contato do site.</p>
<ul>
<li><strong>Criar</strong>: Adicione novos assuntos (ex: "Orçamento", "Suporte Técnico", "Parceria")</li>
<li><strong>Editar</strong>: Altere o nome ou a descrição dos assuntos existentes</li>
<li><strong>Ativar/Desativar</strong>: Assuntos desativados não aparecem no formulário, mas o histórico é mantido</li>
<li><strong>Excluir</strong>: Remova assuntos não utilizados</li>
</ul>
</div>
</div>
<!-- Section 7: Serviços -->
<div class="card shadow mb-4" id="servicos">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-briefcase me-2"></i>7. Serviços</h6>
</div>
<div class="card-body">
<p>No menu <strong>Serviços</strong>, você gerencia os serviços oferecidos pela empresa.</p>
<h6 class="mt-2">Como cadastrar um serviço:</h6>
<ol>
<li>Clique em <strong>"Novo Serviço"</strong></li>
<li>Preencha o <strong>nome</strong> do serviço</li>
<li>Adicione uma <strong>descrição</strong> detalhada (suporta formatação HTML)</li>
<li>Defina se o serviço está <strong>ativo</strong> ou <strong>inativo</strong></li>
<li>Marque como <strong>destaque</strong> para que apareça em primeiro lugar</li>
<li>Clique em <strong>"Salvar"</strong></li>
</ol>
<div class="alert alert-info">
<i class="bi bi-lightbulb me-1"></i>
Serviços inativos não aparecem no site público, mas permanecem salvos no sistema.
</div>
</div>
</div>
<!-- Section 8: FAQ -->
<div class="card shadow mb-4" id="faq">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-question-circle me-2"></i>8. Perguntas Frequentes (FAQ)</h6>
</div>
<div class="card-body">
<p>No menu <strong>FAQ</strong>, você gerencia as perguntas frequentes exibidas no site.</p>
<h6 class="mt-2">Como cadastrar:</h6>
<ol>
<li>Clique em <strong>"Nova Pergunta"</strong></li>
<li>Digite a <strong>pergunta</strong></li>
<li>Digite a <strong>resposta</strong></li>
<li>Defina a <strong>ordem</strong> de exibição (números menores aparecem primeiro)</li>
<li>Marque como <strong>ativa</strong> para que apareça no site</li>
<li>Clique em <strong>"Salvar"</strong></li>
</ol>
<div class="alert alert-info">
<i class="bi bi-lightbulb me-1"></i>
<strong>Dica:</strong> Coloque as perguntas mais comuns com ordem menor (1, 2, 3...) para que apareçam primeiro.
</div>
</div>
</div>
<!-- Section 9: Notícias -->
<div class="card shadow mb-4" id="noticias">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-newspaper me-2"></i>9. Notícias</h6>
</div>
<div class="card-body">
<p>No menu <strong>Notícias</strong>, você gerencia artigos de notícias publicados no site.</p>
<h6 class="mt-2">Como criar uma notícia:</h6>
<ol>
<li>Clique em <strong>"Nova Notícia"</strong></li>
<li>Preencha o <strong>título</strong> da notícia</li>
<li>O <strong>slug</strong> (endereço URL) é gerado automaticamente a partir do título, mas pode ser editado manualmente</li>
<li>Escreva um <strong>resumo</strong> breve que aparecerá na listagem de notícias</li>
<li>Escreva o <strong>conteúdo</strong> completo no editor</li>
<li>Defina o <strong>autor</strong> da notícia</li>
<li>Defina a <strong>data/hora de publicação</strong></li>
<li>Faça upload da <strong>imagem principal</strong> (imagem de destaque)</li>
<li>Configure os <strong>campos SEO</strong>:
<ul>
<li><strong>Título SEO</strong>: Título que aparece nos resultados do Google</li>
<li><strong>Meta Description</strong>: Descrição que aparece nos resultados de busca</li>
<li><strong>Palavras-chave</strong>: Termos relevantes para indexação</li>
</ul>
</li>
<li>Marque como <strong>ativa</strong> para publicar</li>
<li>Clique em <strong>"Salvar"</strong></li>
</ol>
<h6 class="mt-3">Galeria de Imagens Adicionais</h6>
<p>Após criar a notícia, você pode adicionar imagens adicionais na tela de edição:</p>
<ol>
<li>Na edição da notícia, use a seção <strong>"Adicionar Imagens"</strong></li>
<li>Selecione uma ou mais imagens</li>
<li>Adicione uma <strong>descrição/legenda</strong> para cada imagem</li>
<li>As imagens podem ser visualizadas em carrossel na página da notícia no site público</li>
</ol>
<div class="alert alert-info">
<i class="bi bi-lightbulb me-1"></i>
<strong>Dica:</strong> Notícias desativadas não aparecem no site, mas permanecem salvas. Use esse recurso para rascunhos.
</div>
</div>
</div>
<!-- Section 10: Downloads -->
<div class="card shadow mb-4" id="downloads">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-download me-2"></i>10. Central de Downloads</h6>
</div>
<div class="card-body">
<p>No menu <strong>Downloads</strong>, você gerencia arquivos disponibilizados para os visitantes do site.</p>
<h6 class="mt-2">Como cadastrar:</h6>
<ol>
<li>Clique em <strong>"Novo Download"</strong></li>
<li>Preencha o <strong>nome</strong> do arquivo</li>
<li>Adicione uma <strong>descrição</strong></li>
<li>Selecione o <strong>tipo</strong>: Driver, Manual, Software ou Outro</li>
<li>Faça o <strong>upload do arquivo</strong> (até 20MB)</li>
<li>Defina se requer <strong>login</strong> para download</li>
<li>Marque como <strong>ativo</strong></li>
<li>Clique em <strong>"Salvar"</strong></li>
</ol>
</div>
</div>
<!-- Section 11: Produtos -->
<div class="card shadow mb-4" id="produtos">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-box me-2"></i>11. Produtos</h6>
</div>
<div class="card-body">
<p>No menu <strong>Produtos</strong>, você gerencia o catálogo de produtos.</p>
<h6 class="mt-2">Categorias de Produtos</h6>
<p>Antes de cadastrar produtos, crie as categorias:</p>
<ol>
<li>Acesse <strong>Produtos > Categorias</strong></li>
<li>Clique em <strong>"Nova Categoria"</strong></li>
<li>Preencha nome e descrição</li>
<li>Clique em <strong>"Salvar"</strong></li>
</ol>
<h6 class="mt-3">Cadastrando um Produto</h6>
<ol>
<li>Acesse <strong>Produtos > Novo Produto</strong></li>
<li>Preencha nome, descrição, preço e categoria</li>
<li>Faça upload da imagem principal</li>
<li>Adicione imagens adicionais à galeria do produto</li>
<li>Marque como <strong>destaque</strong> se desejar</li>
<li>Ative o produto e clique em <strong>"Salvar"</strong></li>
</ol>
</div>
</div>
<!-- Section 12: Galerias -->
<div class="card shadow mb-4" id="galerias">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-images me-2"></i>12. Galerias de Imagens</h6>
</div>
<div class="card-body">
<p>No menu <strong>Galerias</strong>, você gerencia álbuns de fotos organizados por categorias.</p>
<h6 class="mt-2">Categorias de Galerias</h6>
<p>As galerias são organizadas por categorias. No site público, o visitante navega pelas categorias no menu e visualiza as galerias de cada uma.</p>
<ol>
<li>Acesse <strong>Galerias > Categorias</strong></li>
<li>Clique em <strong>"Nova Categoria"</strong></li>
<li>Preencha nome e descrição</li>
<li>Clique em <strong>"Salvar"</strong></li>
</ol>
<h6 class="mt-3">Criando uma Galeria</h6>
<ol>
<li>Clique em <strong>"Nova Galeria"</strong></li>
<li>Preencha o <strong>título</strong> da galeria</li>
<li>Adicione uma <strong>descrição</strong></li>
<li>Selecione a <strong>categoria</strong></li>
<li>Clique em <strong>"Salvar"</strong></li>
</ol>
<h6 class="mt-3">Adicionando Imagens</h6>
<ol>
<li>Abra a galeria para edição</li>
<li>Na seção de upload, selecione uma ou mais imagens (até 5MB cada)</li>
<li>Após o upload, você pode adicionar <strong>legendas/descrições</strong> para cada imagem</li>
<li>Reordene as imagens conforme necessário</li>
</ol>
</div>
</div>
<!-- Section 13: Páginas -->
<div class="card shadow mb-4" id="paginas">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-file-earmark-text me-2"></i>13. Páginas Institucionais</h6>
</div>
<div class="card-body">
<p>No menu <strong>Páginas</strong>, você gerencia as páginas institucionais do site (Sobre Nós, Missão, etc.).</p>
<h6 class="mt-2">Como criar uma página:</h6>
<ol>
<li>Clique em <strong>"Nova Página"</strong></li>
<li>Preencha o <strong>título</strong> da página</li>
<li>O <strong>slug</strong> é gerado automaticamente (ex: <code>/sobre-nos</code>)</li>
<li>Escreva o <strong>conteúdo</strong> no editor visual</li>
<li>Configure os <strong>campos SEO</strong>:
<ul>
<li><strong>Título SEO</strong>: Aparece na aba do navegador e nos resultados do Google</li>
<li><strong>Meta Description</strong>: Descrição exibida nos resultados de busca</li>
</ul>
</li>
<li>Marque como <strong>ativa</strong> para publicar</li>
<li>Clique em <strong>"Salvar"</strong></li>
</ol>
<div class="alert alert-info">
<i class="bi bi-lightbulb me-1"></i>
<strong>Dica:</strong> Páginas ativas aparecem automaticamente no menu de navegação do site público.
</div>
</div>
</div>
<!-- Section 14: Marketing -->
<div class="card shadow mb-4" id="marketing">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-megaphone me-2"></i>14. Marketing</h6>
</div>
<div class="card-body">
<p>A seção de <strong>Marketing</strong> oferece ferramentas para divulgar seu negócio e analisar visitantes.</p>
<h6 class="mt-2"><i class="bi bi-graph-up me-1"></i>Análise de Visitantes</h6>
<ul>
<li><strong>Gráfico de acessos</strong>: Visualize o tráfego dos últimos 7 dias</li>
<li><strong>Geolocalização</strong>: Veja de quais países e cidades os visitantes acessam seu site</li>
<li><strong>Páginas mais visitadas</strong>: Descubra quais conteúdos atraem mais visitantes</li>
</ul>
<h6 class="mt-3"><i class="bi bi-image me-1"></i>Banners da Home</h6>
<ul>
<li>Gerencie os banners que aparecem na página inicial do site</li>
<li>Faça upload de imagens de alta qualidade (recomendado: 1920x600px)</li>
<li>Defina título, subtítulo e link de redirecionamento para cada banner</li>
<li>Controle a ordem e o status (ativo/inativo) de cada banner</li>
</ul>
<h6 class="mt-3"><i class="bi bi-share me-1"></i>Promover Produtos e Serviços</h6>
<ul>
<li>Selecione um produto ou serviço específico</li>
<li>Obtenha links diretos para compartilhamento</li>
<li>Use os botões de WhatsApp, Facebook e LinkedIn para divulgar rapidamente</li>
</ul>
<h6 class="mt-3"><i class="bi bi-envelope-heart me-1"></i>Email Marketing</h6>
<ul>
<li>Redija um comunicado com assunto e corpo do e-mail</li>
<li>Vincule um produto ou serviço para inclusão automática de imagem e link</li>
<li>Ao enviar, todos os usuários cadastrados receberão a mensagem formatada</li>
</ul>
</div>
</div>
<!-- Section 15: Configurações -->
<div class="card shadow mb-4" id="configuracoes">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-gear me-2"></i>15. Configurações do Sistema</h6>
</div>
<div class="card-body">
<p>No menu <strong>Dados da Empresa</strong>, você gerencia as configurações globais do site:</p>
<h6 class="mt-2">Dados da Empresa</h6>
<ul>
<li><strong>Nome da empresa</strong>: Exibido no cabeçalho e rodapé do site</li>
<li><strong>CNPJ</strong>: Informação legal da empresa</li>
<li><strong>Endereço</strong>: Exibido no rodapé e na página de contato</li>
<li><strong>Telefone</strong>: Utilizado também para o botão flutuante do WhatsApp</li>
<li><strong>E-mail</strong>: E-mail principal de contato</li>
</ul>
<h6 class="mt-3">Redes Sociais</h6>
<ul>
<li>Configure os links do <strong>Facebook</strong>, <strong>Instagram</strong>, <strong>LinkedIn</strong> e <strong>YouTube</strong></li>
<li>Os ícones das redes sociais aparecem automaticamente no rodapé do site</li>
</ul>
<h6 class="mt-3">WhatsApp</h6>
<ul>
<li><strong>Ativar/Desativar</strong>: Controle a exibição do botão flutuante</li>
<li><strong>Horário de funcionamento</strong>: Defina horário de início, término e pausa para almoço</li>
<li><strong>Mensagem padrão</strong>: Texto pré-preenchido quando o visitante clica no botão</li>
</ul>
<h6 class="mt-3">SEO Global</h6>
<ul>
<li><strong>Título padrão</strong>: Título exibido nas abas do navegador</li>
<li><strong>Palavras-chave</strong>: Termos para indexação global do site</li>
</ul>
<h6 class="mt-3">Scripts de Rastreamento</h6>
<ul>
<li>Insira códigos como <strong>Google Analytics</strong> ou <strong>Facebook Pixel</strong></li>
<li>Os scripts são injetados automaticamente em todas as páginas</li>
</ul>
<h6 class="mt-3">Modo Manutenção</h6>
<ul>
<li>Ative para exibir uma página de "Em Manutenção" para visitantes</li>
<li>Enquanto ativo, administradores continuam tendo acesso ao painel</li>
</ul>
</div>
</div>
<!-- Section 16: Perfil -->
<div class="card shadow mb-4" id="perfil">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-person-circle me-2"></i>16. Perfil e Preferências</h6>
</div>
<div class="card-body">
<h6 class="mt-2"><i class="bi bi-pencil me-1"></i>Editar Perfil</h6>
<p>Em <strong>Configurações > Perfil</strong>, você pode alterar:</p>
<ul>
<li><strong>Nome</strong> completo</li>
<li><strong>E-mail</strong></li>
<li><strong>Avatar</strong> (foto de perfil)</li>
<li><strong>Senha</strong> de acesso</li>
</ul>
<h6 class="mt-3"><i class="bi bi-sliders me-1"></i>Preferências</h6>
<p>Em <strong>Configurações > Preferências</strong>, você pode personalizar:</p>
<ul>
<li><strong>Modo escuro</strong>: Ative/desative o tema escuro no painel administrativo</li>
<li><strong>Notificações por e-mail</strong>: Controle o recebimento de notificações</li>
</ul>
</div>
</div>
<!-- Section 17: Notificações -->
<div class="card shadow mb-4" id="notificacoes">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-bell me-2"></i>17. Notificações</h6>
</div>
<div class="card-body">
<p>O sistema envia notificações automáticas para os administradores. Elas aparecem no ícone de sino na barra superior.</p>
<h6 class="mt-2">Eventos que geram notificações:</h6>
<ul>
<li><strong>Novo usuário cadastrado</strong>: Quando alguém se registra no site</li>
<li><strong>Nova mensagem de contato</strong>: Quando um visitante envia uma mensagem</li>
<li><strong>Conteúdo criado/alterado</strong>: Quando páginas, galerias, notícias, produtos ou serviços são criados ou modificados</li>
</ul>
<h6 class="mt-3">Gerenciando notificações:</h6>
<ul>
<li>Clique no <strong>ícone de sino</strong> na barra superior para ver as notificações não lidas</li>
<li>Clique em uma notificação para ser redirecionado ao conteúdo relacionado</li>
<li>Clique em <strong>"Marcar todas como lidas"</strong> para limpar a lista</li>
</ul>
</div>
</div>
<!-- Section 18: Dicas -->
<div class="card shadow mb-4" id="dicas">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><i class="bi bi-stars me-2"></i>18. Dicas e Boas Práticas</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h6 class="mt-2"><i class="bi bi-search me-1"></i>SEO</h6>
<ul>
<li>Sempre preencha os campos de <strong>Título SEO</strong> e <strong>Meta Description</strong> em páginas e notícias</li>
<li>Use palavras-chave relevantes no conteúdo</li>
<li>Mantenha os slugs curtos e descritivos</li>
<li>Utilize imagens com textos alternativos</li>
</ul>
<h6 class="mt-3"><i class="bi bi-image me-1"></i>Imagens</h6>
<ul>
<li>Use imagens otimizadas para web (formato WebP ou JPEG comprimido)</li>
<li>Banners: resolução recomendada de <strong>1920x600px</strong></li>
<li>Imagens de galeria: limite de <strong>5MB</strong> por arquivo</li>
<li>Downloads: limite de <strong>20MB</strong> por arquivo</li>
</ul>
</div>
<div class="col-md-6">
<h6 class="mt-2"><i class="bi bi-shield-check me-1"></i>Segurança</h6>
<ul>
<li>Altere a senha padrão após o primeiro acesso</li>
<li>Use senhas fortes com letras, números e caracteres especiais</li>
<li>Revise periodicamente as permissões dos usuários</li>
<li>Desative usuários que não precisam mais de acesso</li>
</ul>
<h6 class="mt-3"><i class="bi bi-clock-history me-1"></i>Manutenção</h6>
<ul>
<li>Ative o <strong>Modo Manutenção</strong> antes de fazer grandes alterações</li>
<li>Revise periodicamente as mensagens de contato</li>
<li>Mantenha o FAQ atualizado para reduzir chamados de suporte</li>
<li>Verifique os dados da empresa periodicamente</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Back to top -->
<div class="text-center mb-4">
<a href="#" class="btn btn-primary btn-sm">
<i class="bi bi-arrow-up me-1"></i>Voltar ao topo
</a>
</div>
</div>
@endsection
+136
View File
@@ -0,0 +1,136 @@
@extends('layouts.admin')
@section('title', 'Análise de Visitantes')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Análise de Visitantes</h1>
<a href="{{ route('admin.marketing.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="row">
<!-- Gráfico de Acessos (Últimos 7 dias) -->
<div class="col-xl-12 col-lg-12">
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Acessos nos Últimos 7 Dias</h6>
</div>
<div class="card-body">
<div class="chart-area">
<canvas id="accessChart" style="height: 300px;"></canvas>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Ranking por País -->
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Top 10 Países</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>País</th>
<th class="text-center">Acessos</th>
</tr>
</thead>
<tbody>
@forelse($countries as $country)
<tr>
<td><i class="bi bi-globe-americas text-muted me-2"></i> {{ $country->country }}</td>
<td class="text-center"><span class="badge badge-primary">{{ $country->total }}</span></td>
</tr>
@empty
<tr><td colspan="2" class="text-center">Nenhum dado capturado ainda.</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Ranking por Cidade -->
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Top 10 Cidades</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Cidade / Região</th>
<th class="text-center">Acessos</th>
</tr>
</thead>
<tbody>
@forelse($cities as $city)
<tr>
<td><i class="bi bi-geo-alt text-danger me-2"></i> {{ $city->city }} ({{ $city->region }})</td>
<td class="text-center"><span class="badge badge-success">{{ $city->total }}</span></td>
</tr>
@empty
<tr><td colspan="2" class="text-center">Nenhum dado capturado ainda.</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="alert alert-info border-0 shadow-sm small">
<i class="bi bi-info-circle me-2"></i> <strong>Nota:</strong> A localização é estimada com base no endereço IP do visitante. A precisão pode variar dependendo do provedor de internet. Os dados são capturados apenas em páginas públicas (não administrativas).
</div>
@endsection
@push('js')
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('accessChart').getContext('2d');
const accessChart = new Chart(ctx, {
type: 'line',
data: {
labels: JSON.parse('<?php echo json_encode($last7Days->pluck("date")); ?>'),
datasets: [{
label: 'Visitas',
data: JSON.parse('<?php echo json_encode($last7Days->pluck("total")); ?>'),
backgroundColor: 'rgba(78, 115, 223, 0.05)',
borderColor: 'rgba(78, 115, 223, 1)',
pointRadius: 3,
pointBackgroundColor: 'rgba(78, 115, 223, 1)',
pointBorderColor: 'rgba(78, 115, 223, 1)',
pointHoverRadius: 3,
pointHoverBackgroundColor: 'rgba(78, 115, 223, 1)',
pointHoverBorderColor: 'rgba(78, 115, 223, 1)',
pointHitRadius: 10,
pointBorderWidth: 2,
fill: true,
tension: 0.3
}]
},
options: {
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
}
}
});
</script>
@endpush
+142
View File
@@ -0,0 +1,142 @@
@extends('layouts.admin')
@section('title', 'E-mail Marketing')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Disparo de E-mail Marketing</h1>
<a href="{{ route('admin.marketing.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<div class="row">
<div class="col-lg-8">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Compor E-mail Promocional</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.marketing.email.send') }}" method="POST">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">Assunto do E-mail</label>
<input type="text" name="subject" class="form-control @error('subject') is-invalid @enderror" value="{{ old('subject') }}" placeholder="Ex: Oferta Especial: 20% de desconto em Notebooks!" required>
@error('subject') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Mensagem</label>
<textarea name="message" id="editor" class="form-control @error('message') is-invalid @enderror" rows="10">{{ old('message') }}</textarea>
@error('message') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Texto do Botão (Opcional)</label>
<input type="text" name="button_text" class="form-control" value="{{ old('button_text') }}" placeholder="Ex: Ver Oferta">
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">URL do Botão (Opcional)</label>
<input type="url" name="button_url" class="form-control" value="{{ old('button_url') }}" placeholder="Ex: https://seusite.com/promo">
</div>
</div>
</div>
<hr>
<div class="form-group mb-4">
<label class="font-weight-bold text-primary"><i class="bi bi-image me-1"></i> Incluir Imagem de Destaque (Opcional)</label>
<div class="row">
<div class="col-md-6">
<label class="small text-muted">Escolher um Produto:</label>
<select name="product_id" class="form-control form-control-sm mb-2">
<option value="">Nenhum produto</option>
@foreach($products as $product)
<option value="{{ $product->id }}">{{ $product->name }}</option>
@endforeach
</select>
</div>
<div class="col-md-6">
<label class="small text-muted">Ou escolher um Serviço:</label>
<select name="service_id" class="form-control form-control-sm mb-2">
<option value="">Nenhum serviço</option>
@foreach($services as $service)
<option value="{{ $service->id }}">{{ $service->name }}</option>
@endforeach
</select>
</div>
</div>
<small class="text-muted">A imagem principal do item selecionado será enviada no topo do e-mail.</small>
</div>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm" onclick="return confirm('Deseja enviar este e-mail para todos os {{ $userCount }} clientes cadastrados?')">
<i class="bi bi-send me-1"></i> Disparar E-mail para {{ $userCount }} Clientes
</button>
</form>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card shadow mb-4">
<div class="card-header py-3 bg-light">
<h6 class="m-0 font-weight-bold text-dark">Informações Importantes</h6>
</div>
<div class="card-body">
<div class="alert alert-info small border-0">
<i class="bi bi-info-circle me-1"></i> Os e-mails serão enviados para todos os usuários com o tipo "User" que possuem a preferência de e-mail ativada.
</div>
<h6 class="font-weight-bold small">Dicas para um bom e-mail:</h6>
<ul class="small text-muted pl-3">
<li>Use um assunto curto e chamativo.</li>
<li>Vá direto ao ponto na mensagem.</li>
<li>Sempre inclua um botão de ação (CTA).</li>
<li>Evite e-mails muito longos com muitas imagens.</li>
</ul>
<hr>
<p class="small text-center text-muted mb-0">Total de destinatários aptos: <br><strong>{{ $userCount }} clientes</strong></p>
</div>
</div>
</div>
</div>
@endsection
@push('css')
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.css" rel="stylesheet">
@endpush
@push('js')
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.js"></script>
<script>
$(document).ready(function() {
$('#editor').summernote({
height: 300,
tabsize: 2,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['view', ['fullscreen', 'codeview']]
]
});
// Garantir que apenas um select de imagem seja usado
$('select[name="product_id"]').change(function() {
if($(this).val() != "") $('select[name="service_id"]').val("");
});
$('select[name="service_id"]').change(function() {
if($(this).val() != "") $('select[name="product_id"]').val("");
});
});
</script>
@endpush
+182
View File
@@ -0,0 +1,182 @@
@extends('layouts.admin')
@section('title', 'Marketing & Promoção')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Marketing & Promoção</h1>
</div>
<div class="row">
<!-- Card Banners -->
<div class="col-xl-4 col-md-6 mb-4">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Destaques do Site</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Gerenciar Banners</div>
<p class="small text-muted mt-2">Crie banners rotativos para a página inicial para promover novidades e ofertas.</p>
<a href="{{ route('admin.marketing.banners.index') }}" class="btn btn-sm btn-primary">Acessar</a>
</div>
<div class="col-auto">
<i class="bi bi-images text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Card Promoção de Produtos -->
<div class="col-xl-4 col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Vendas Rápidas</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Promover Produtos</div>
<p class="small text-muted mt-2">Gere links de compartilhamento para WhatsApp e Redes Sociais com mensagens prontas.</p>
<a href="{{ route('admin.marketing.promote.products') }}" class="btn btn-sm btn-success">Acessar</a>
</div>
<div class="col-auto">
<i class="bi bi-share text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Card Promoção de Serviços -->
<div class="col-xl-4 col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Atrair Clientes</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Promover Serviços</div>
<p class="small text-muted mt-2">Promova seus serviços especializados e atraia novas solicitações de orçamento.</p>
<a href="{{ route('admin.marketing.promote.services') }}" class="btn btn-sm btn-warning text-white">Acessar</a>
</div>
<div class="col-auto">
<i class="bi bi-bell text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Card E-mail Marketing -->
<div class="col-xl-4 col-md-6 mb-4">
<div class="card border-left-danger shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
Fidelização</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">E-mail Marketing</div>
<p class="small text-muted mt-2">Envie promoções, novidades e ofertas personalizadas para todos os seus clientes por e-mail.</p>
<a href="{{ route('admin.marketing.email') }}" class="btn btn-sm btn-danger shadow-sm">Configurar Disparo</a>
</div>
<div class="col-auto">
<i class="bi bi-envelope-open text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Card Visitantes -->
<div class="col-xl-4 col-md-6 mb-4">
<div class="card border-left-dark shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-dark text-uppercase mb-1">
Geolocalização</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Análise de Visitantes</div>
<p class="small text-muted mt-2">Visualize de quais cidades e países as pessoas estão acessando o seu site em tempo real.</p>
<a href="{{ route('admin.marketing.analytics') }}" class="btn btn-sm btn-dark shadow-sm">Ver Relatórios</a>
</div>
<div class="col-auto">
<i class="bi bi-geo-alt text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Card SEO -->
<div class="col-xl-4 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col me-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
Visibilidade</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">Configurações de SEO</div>
<p class="small text-muted mt-2">Ajuste as meta-tags globais do site para melhorar o ranqueamento no Google.</p>
<a href="{{ route('admin.settings.index') }}#seo" class="btn btn-sm btn-info">Configurar</a>
</div>
<div class="col-auto">
<i class="bi bi-search text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Promoção SysCRM -->
<div class="card shadow mb-4 border-bottom-primary overflow-hidden">
<div class="row no-gutters">
<div class="col-md-4 bg-primary d-flex align-items-center justify-content-center p-5">
<div class="text-center text-white">
<i class="bi bi-people mb-3"></i>
<h2 class="font-weight-bold">SysCRM</h2>
<p class="lead">Gestão de Relacionamento</p>
</div>
</div>
<div class="col-md-8">
<div class="card-body p-5">
<h3 class="font-weight-bold text-primary mb-3">Potencialize suas vendas com o SysCRM</h3>
<p class="text-muted lead">Integre sua estratégia de marketing com a melhor ferramenta de gestão de clientes. O SysCRM permite que você acompanhe cada lead gerado pelo seu site, organize seu funil de vendas e nunca perca um negócio.</p>
<ul class="list-unstyled mb-4">
<li class="mb-2"><i class="bi bi-check-circle text-success me-2"></i> Funil de Vendas Visual e Intuitivo</li>
<li class="mb-2"><i class="bi bi-check-circle text-success me-2"></i> Gestão de Contatos e Histórico Completo</li>
<li class="mb-2"><i class="bi bi-check-circle text-success me-2"></i> Automação de Tarefas e Lembretes</li>
<li><i class="bi bi-check-circle text-success me-2"></i> Integração Direta com seu Site</li>
</ul>
<div class="d-flex gap-3">
<a href="https://syscrm.syspanel.com.br" target="_blank" class="btn btn-primary btn-lg px-5 shadow-sm">
<i class="bi bi-box-arrow-up-right me-2"></i> Conhecer o SysCRM
</a>
<a href="https://wa.me/5535992261684?text=Olá! Tenho interesse no SysCRM." target="_blank" class="btn btn-success btn-lg px-5 shadow-sm">
<i class="bi bi-whatsapp me-2"></i> Tenho Interesse
</a>
</div>
</div>
</div>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Dicas de Marketing</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h5 class="font-weight-bold"><i class="bi bi-whatsapp text-success me-2"></i> WhatsApp Marketing</h5>
<p>Use a ferramenta de <strong>Promover Produtos</strong> para enviar ofertas personalizadas aos seus clientes. Uma mensagem com foto e link direto aumenta em 40% a chance de conversão.</p>
</div>
<div class="col-md-6">
<h5 class="font-weight-bold"><i class="bi bi-megaphone text-primary me-2"></i> Banners Estratégicos</h5>
<p>Mantenha sempre pelo menos 2 banners ativos: um com um produto em destaque e outro com um serviço ou diferencial da sua empresa (ex: "Orçamento Grátis").</p>
</div>
</div>
</div>
</div>
@endsection
+116
View File
@@ -0,0 +1,116 @@
@extends('layouts.admin')
@section('title', 'Promover Produtos')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Promover Produtos</h1>
<a href="{{ route('admin.marketing.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Ferramentas de Compartilhamento</h6>
</div>
<div class="card-body">
<p class="text-muted mb-4">Escolha um produto abaixo para gerar links de compartilhamento rápido em suas redes sociais e WhatsApp.</p>
<div class="table-responsive">
<table class="table table-hover border" width="100%" cellspacing="0">
<thead class="bg-light">
<tr>
<th width="80">Foto</th>
<th>Produto</th>
<th>Categoria</th>
<th>Preço</th>
<th width="350">Links de Promoção</th>
</tr>
</thead>
<tbody>
@foreach($products as $product)
<tr>
<td>
@if($product->image)
<img src="{{ asset('storage/' . $product->image) }}" class="img-thumbnail" style="height: 40px; width: 40px; object-fit: cover;">
@else
<div class="bg-light d-flex align-items-center justify-content-center" style="height: 40px; width: 40px;">
<i class="bi bi-box text-muted"></i>
</div>
@endif
</td>
<td class="font-weight-bold text-dark">{{ $product->name }}</td>
<td>
<span class="badge badge-info">{{ $product->category->name ?? 'Sem Categoria' }}</span>
</td>
<td>R$ {{ number_format($product->price, 2, ',', '.') }}</td>
<td>
@php
$productLink = route('produtos', ['categoria' => $product->category->slug ?? '']);
$productPrice = number_format($product->price, 2, ',', '.');
$rawMessage = \App\Models\Setting::get('marketing_product_text', 'Confira este produto incrível: {name} por apenas R$ {price}. Veja mais detalhes aqui: {link}');
$shareMessage = str_replace(
['{name}', '{price}', '{link}'],
[$product->name, $productPrice, $productLink],
$rawMessage
);
@endphp
<div class="btn-group">
<!-- WhatsApp Share -->
<a href="https://wa.me/?text={{ urlencode($shareMessage) }}"
target="_blank" class="btn btn-sm btn-success" title="Enviar para WhatsApp">
<i class="bi bi-whatsapp me-1"></i> WhatsApp
</a>
<!-- Facebook Share -->
<a href="https://www.facebook.com/sharer/sharer.php?u={{ urlencode($productLink) }}"
target="_blank" class="btn btn-sm btn-primary" title="Compartilhar no Facebook">
<i class="bi bi-facebook me-1"></i> Facebook
</a>
<!-- LinkedIn Share -->
<a href="https://www.linkedin.com/sharing/share-offsite/?url={{ urlencode($productLink) }}"
target="_blank" class="btn btn-sm btn-info" title="Compartilhar no LinkedIn">
<i class="bi bi-linkedin me-1"></i> LinkedIn
</a>
<!-- Copy Link -->
<button type="button" class="btn btn-sm btn-light border copy-link"
data-url="{{ $productLink }}" title="Copiar Link">
<i class="bi bi-link-45deg"></i>
</button>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endsection
@push('js')
<script>
$(document).ready(function() {
$('.copy-link').click(function() {
var url = $(this).data('url');
var tempInput = $("<input>");
$("body").append(tempInput);
tempInput.val(url).select();
document.execCommand("copy");
tempInput.remove();
$(this).removeClass('btn-light').addClass('btn-dark text-white');
var btn = $(this);
setTimeout(function() {
btn.removeClass('btn-dark text-white').addClass('btn-light');
}, 1000);
alert('Link copiado para a área de transferência!');
});
});
</script>
@endpush
+107
View File
@@ -0,0 +1,107 @@
@extends('layouts.admin')
@section('title', 'Promover Serviços')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Promover Serviços</h1>
<a href="{{ route('admin.marketing.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Ferramentas de Compartilhamento de Serviços</h6>
</div>
<div class="card-body">
<p class="text-muted mb-4">Escolha um serviço abaixo para gerar links de compartilhamento rápido e atrair novos orçamentos.</p>
<div class="table-responsive">
<table class="table table-hover border" width="100%" cellspacing="0">
<thead class="bg-light">
<tr>
<th width="80">Ícone</th>
<th>Serviço</th>
<th width="350">Links de Promoção</th>
</tr>
</thead>
<tbody>
@foreach($services as $service)
<tr>
<td class="text-center">
@if($service->icon)
<i class="{{ $service->icon }} text-primary"></i>
@else
<i class="bi bi-bell text-muted"></i>
@endif
</td>
<td class="font-weight-bold text-dark">{{ $service->name }}</td>
<td>
@php
$serviceLink = route('servicos');
$rawMessage = \App\Models\Setting::get('marketing_service_text', 'Precisa de {name}? Nós podemos te ajudar! Confira nossos serviços aqui: {link}');
$shareMessage = str_replace(
['{name}', '{link}'],
[$service->name, $serviceLink],
$rawMessage
);
@endphp
<div class="btn-group">
<!-- WhatsApp Share -->
<a href="https://wa.me/?text={{ urlencode($shareMessage) }}"
target="_blank" class="btn btn-sm btn-success" title="Enviar para WhatsApp">
<i class="bi bi-whatsapp me-1"></i> WhatsApp
</a>
<!-- Facebook Share -->
<a href="https://www.facebook.com/sharer/sharer.php?u={{ urlencode($serviceLink) }}"
target="_blank" class="btn btn-sm btn-primary" title="Compartilhar no Facebook">
<i class="bi bi-facebook me-1"></i> Facebook
</a>
<!-- LinkedIn Share -->
<a href="https://www.linkedin.com/sharing/share-offsite/?url={{ urlencode($serviceLink) }}"
target="_blank" class="btn btn-sm btn-info" title="Compartilhar no LinkedIn">
<i class="bi bi-linkedin me-1"></i> LinkedIn
</a>
<!-- Copy Link -->
<button type="button" class="btn btn-sm btn-light border copy-link"
data-url="{{ $serviceLink }}" title="Copiar Link">
<i class="bi bi-link-45deg"></i>
</button>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endsection
@push('js')
<script>
$(document).ready(function() {
$('.copy-link').click(function() {
var url = $(this).data('url');
var tempInput = $("<input>");
$("body").append(tempInput);
tempInput.val(url).select();
document.execCommand("copy");
tempInput.remove();
$(this).removeClass('btn-light').addClass('btn-dark text-white');
var btn = $(this);
setTimeout(function() {
btn.removeClass('btn-dark text-white').addClass('btn-light');
}, 1000);
alert('Link copiado para a área de transferência!');
});
});
</script>
@endpush
+111
View File
@@ -0,0 +1,111 @@
@extends('layouts.admin')
@section('title', 'Nova Notícia')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Criar Notícia</h1>
<a href="{{ route('admin.news.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações da Notícia</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.news.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">Título</label>
<input type="text" name="title" id="title" class="form-control @error('title') is-invalid @enderror" value="{{ old('title') }}" required placeholder="Ex: Lançamento de novo produto">
@error('title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Slug (URL)</label>
<input type="text" name="slug" id="slug" class="form-control @error('slug') is-invalid @enderror" value="{{ old('slug') }}" required>
@error('slug') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Autor</label>
<input type="text" name="author" class="form-control @error('author') is-invalid @enderror" value="{{ old('author') }}" placeholder="Nome do autor">
@error('author') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Data/Hora de Publicação</label>
<input type="datetime-local" name="published_at" class="form-control @error('published_at') is-invalid @enderror" value="{{ old('published_at') }}">
@error('published_at') <div class="invalid-feedback">{{ $message }}</div> @enderror
<small class="text-muted">Deixe vazio para publicar imediatamente.</small>
</div>
</div>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Imagem Principal</label>
<input type="file" name="featured_image" class="form-control-file @error('featured_image') is-invalid @enderror" accept="image/*">
@error('featured_image') <div class="invalid-feedback">{{ $message }}</div> @enderror
<small class="text-muted">Imagem de destaque da notícia (máx. 5MB).</small>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Resumo</label>
<textarea name="summary" class="form-control @error('summary') is-invalid @enderror" rows="2" maxlength="500">{{ old('summary') }}</textarea>
@error('summary') <div class="invalid-feedback">{{ $message }}</div> @enderror
<small class="text-muted">Breve descrição exibida na listagem (máx. 500 caracteres).</small>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Conteúdo</label>
<textarea name="content" class="form-control @error('content') is-invalid @enderror" rows="10">{{ old('content') }}</textarea>
@error('content') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<hr>
<h6 class="font-weight-bold text-muted mb-3">SEO (Opcional)</h6>
<div class="form-group mb-3">
<label class="font-weight-bold">Título SEO</label>
<input type="text" name="seo_title" class="form-control @error('seo_title') is-invalid @enderror" value="{{ old('seo_title') }}" placeholder="Título para mecanismos de busca">
@error('seo_title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição SEO</label>
<textarea name="seo_description" class="form-control @error('seo_description') is-invalid @enderror" rows="2" maxlength="500">{{ old('seo_description') }}</textarea>
@error('seo_description') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Palavras-chave SEO</label>
<input type="text" name="seo_keywords" class="form-control @error('seo_keywords') is-invalid @enderror" value="{{ old('seo_keywords') }}" placeholder="palavra1, palavra2, palavra3">
@error('seo_keywords') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Criar Notícia
</button>
</form>
</div>
</div>
@endsection
@push('js')
<script>
document.getElementById('title').addEventListener('keyup', function() {
let text = this.value.toLowerCase()
.normalize('NFD').replace(/[\u0300-\u036f]/g, "")
.replace(/[^\w ]+/g, '')
.replace(/ +/g, '-');
document.getElementById('slug').value = text;
});
</script>
@endpush
+168
View File
@@ -0,0 +1,168 @@
@extends('layouts.admin')
@section('title', 'Editar Notícia')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar Notícia: {{ $news->title }}</h1>
<a href="{{ route('admin.news.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<div class="row">
<!-- News Settings -->
<div class="col-lg-4">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Configurações</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.news.update', $news) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="form-group mb-3">
<label class="small font-weight-bold">Título</label>
<input type="text" name="title" id="title" class="form-control" value="{{ old('title', $news->title) }}" required>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">URL (Slug)</label>
<input type="text" name="slug" id="slug" class="form-control" value="{{ old('slug', $news->slug) }}" required>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Autor</label>
<input type="text" name="author" class="form-control" value="{{ old('author', $news->author) }}">
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Data/Hora de Publicação</label>
<input type="datetime-local" name="published_at" class="form-control" value="{{ old('published_at', $news->published_at ? $news->published_at->format('Y-m-d\TH:i') : '') }}">
<small class="text-muted">Vazio = publicação imediata.</small>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ $news->active ? 'selected' : '' }}>Ativa</option>
<option value="0" {{ !$news->active ? 'selected' : '' }}>Inativa</option>
</select>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Imagem Principal</label>
@if($news->featured_image)
<div class="mb-2">
<img src="{{ asset('storage/' . $news->featured_image) }}" alt="Featured" class="img-thumbnail" style="max-height: 120px;">
</div>
<a href="{{ route('admin.news.remove-featured', $news) }}" class="btn btn-sm btn-outline-danger mb-2" onclick="return confirm('Remover imagem principal?')">
<i class="bi bi-x-lg"></i> Remover Imagem
</a>
@endif
<input type="file" name="featured_image" class="form-control-file" accept="image/*">
<small class="text-muted d-block mt-1">Envie uma nova imagem para substituir a atual.</small>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Resumo</label>
<textarea name="summary" class="form-control" rows="2" maxlength="500">{{ old('summary', $news->summary) }}</textarea>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Conteúdo</label>
<textarea name="content" class="form-control" rows="8">{{ old('content', $news->content) }}</textarea>
</div>
<hr>
<h6 class="small font-weight-bold text-muted">SEO</h6>
<div class="form-group mb-3">
<label class="small font-weight-bold">Título SEO</label>
<input type="text" name="seo_title" class="form-control" value="{{ old('seo_title', $news->seo_title) }}">
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Descrição SEO</label>
<textarea name="seo_description" class="form-control" rows="2">{{ old('seo_description', $news->seo_description) }}</textarea>
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">Palavras-chave SEO</label>
<input type="text" name="seo_keywords" class="form-control" value="{{ old('seo_keywords', $news->seo_keywords) }}">
</div>
<button type="submit" class="btn btn-primary btn-block">Salvar Alterações</button>
</form>
</div>
</div>
<!-- Upload Additional Images -->
<div class="card shadow mb-4">
<div class="card-header py-3 bg-light">
<h6 class="m-0 font-weight-bold text-dark">Adicionar Imagens</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.news.upload', $news) }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="form-group mb-3">
<label class="small font-weight-bold">Selecionar Imagens</label>
<input type="file" name="images[]" class="form-control-file" multiple accept="image/*" required>
<small class="text-muted">Selecione uma ou mais imagens (máx. 5MB cada).</small>
</div>
<button type="submit" class="btn btn-success btn-block">
<i class="bi bi-upload me-1"></i> Enviar Imagens
</button>
</form>
</div>
</div>
</div>
<!-- Additional Images List -->
<div class="col-lg-8">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Imagens da Notícia</h6>
</div>
<div class="card-body">
<div class="row">
@forelse($news->images as $img)
<div class="col-md-6 mb-4">
<div class="card h-100 border-0 shadow-sm overflow-hidden">
<img src="{{ asset('storage/' . $img->file_path) }}" class="card-img-top" style="height: 150px; object-fit: cover;">
<div class="card-body p-3">
<form action="{{ route('admin.news.image.update', $img) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group mb-2">
<input type="text" name="description" class="form-control form-control-sm" value="{{ $img->description }}" placeholder="Descrição da imagem">
</div>
<div class="d-flex gap-2">
<input type="number" name="order" class="form-control form-control-sm w-25" value="{{ $img->order }}" title="Ordem">
<button type="submit" class="btn btn-sm btn-primary flex-grow-1">Salvar</button>
</div>
</form>
<form action="{{ route('admin.news.image.delete', $img) }}" method="POST" class="mt-2">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-outline-danger btn-block" onclick="return confirm('Remover esta imagem?')">Excluir</button>
</form>
</div>
</div>
</div>
@empty
<div class="col-12 text-center py-5">
<p class="text-muted">Nenhuma imagem adicional adicionada.</p>
</div>
@endforelse
</div>
</div>
</div>
</div>
</div>
@endsection
+101
View File
@@ -0,0 +1,101 @@
@extends('layouts.admin')
@section('title', 'Gerenciar Notícias')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">
<i class="bi bi-newspaper me-2"></i>Notícias
<span class="badge badge-{{ $newsEnabled ? 'success' : 'secondary' }} ml-2" style="font-size: 0.7rem;">
{{ $newsEnabled ? 'Ativo' : 'Inativo' }}
</span>
</h1>
<div class="d-flex gap-2">
<form action="{{ route('admin.news.toggle') }}" method="POST">
@csrf
<button type="submit" class="btn btn-sm shadow-sm {{ $newsEnabled ? 'btn-outline-warning' : 'btn-outline-success' }}">
<i class="bi bi-{{ $newsEnabled ? 'eye-slash' : 'eye' }} me-1"></i>
{{ $newsEnabled ? 'Desativar Módulo' : 'Ativar Módulo' }}
</button>
</form>
<a href="{{ route('admin.news.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Nova Notícia
</a>
</div>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Notícias</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Imagem</th>
<th>Título</th>
<th>Autor</th>
<th>Publicação</th>
<th>Imagens</th>
<th>Status</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($newsList as $item)
<tr>
<td>
@if($item->featured_image)
<img src="{{ asset('storage/' . $item->featured_image) }}" alt="{{ $item->title }}" style="width: 60px; height: 40px; object-fit: cover; border-radius: 4px;">
@else
<div class="bg-light d-flex align-items-center justify-content-center" style="width: 60px; height: 40px; border-radius: 4px;">
<i class="bi bi-image text-muted"></i>
</div>
@endif
</td>
<td>{{ $item->title }}</td>
<td>{{ $item->author ?? '—' }}</td>
<td>
@if($item->published_at)
{{ $item->published_at->format('d/m/Y H:i') }}
@else
<span class="text-muted">—</span>
@endif
</td>
<td>{{ $item->images_count }} imagens</td>
<td>
<span class="badge badge-{{ $item->active ? 'success' : 'secondary' }}">
{{ $item->active ? 'Ativa' : 'Inativa' }}
</span>
</td>
<td>
<a href="{{ route('admin.news.edit', $item) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i> Editar
</a>
<a href="{{ route('news.show', $item->slug) }}" target="_blank" class="btn btn-sm btn-info">
<i class="bi bi-eye"></i> Ver
</a>
<form action="{{ route('admin.news.destroy', $item) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Excluir esta notícia e TODAS as suas imagens?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-4">
{{ $newsList->links() }}
</div>
</div>
</div>
@endsection
+116
View File
@@ -0,0 +1,116 @@
@extends('layouts.admin')
@section('title', 'Nova Página')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Nova Página</h1>
<a href="{{ route('admin.pages.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Criar Conteúdo</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.pages.store') }}" method="POST">
@csrf
<div class="row">
<div class="col-md-8">
<div class="form-group mb-3">
<label class="font-weight-bold">Título da Página</label>
<input type="text" name="title" id="title" class="form-control @error('title') is-invalid @enderror" value="{{ old('title') }}" required>
@error('title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Conteúdo (HTML)</label>
<textarea name="content" id="editor" class="form-control @error('content') is-invalid @enderror" rows="15">{{ old('content') }}</textarea>
@error('content') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-3">
<label class="font-weight-bold">Slug (URL amigável)</label>
<input type="text" name="slug" id="slug" class="form-control @error('slug') is-invalid @enderror" value="{{ old('slug') }}" required>
<small class="text-muted">Ex: minha-nova-pagina</small>
@error('slug') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Meta Description (SEO)</label>
<textarea name="meta_description" class="form-control @error('meta_description') is-invalid @enderror" rows="3">{{ old('meta_description') }}</textarea>
@error('meta_description') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<hr>
<h6 class="font-weight-bold text-primary mb-3"><i class="bi bi-search me-1"></i> SEO Adicional</h6>
<div class="form-group mb-3">
<label class="small font-weight-bold">Palavras-chave</label>
<input type="text" name="meta_keywords" class="form-control form-control-sm" value="{{ old('meta_keywords') }}" placeholder="Ex: computador, assistência">
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">URL Canônica</label>
<input type="text" name="canonical_url" class="form-control form-control-sm" value="{{ old('canonical_url') }}">
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Status da Página</label>
<select name="active" class="form-control">
<option value="1" {{ old('active', '1') == '1' ? 'selected' : '' }}>Ativa (Visível no site)</option>
<option value="0" {{ old('active') == '0' ? 'selected' : '' }}>Inativa (Oculta)</option>
</select>
</div>
</div>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Criar Página
</button>
</form>
</div>
</div>
@endsection
@push('css')
<!-- Incluindo o editor Summernote para facilitar a edição HTML -->
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.css" rel="stylesheet">
@endpush
@push('js')
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.js"></script>
<script>
$(document).ready(function() {
$('#editor').summernote({
height: 400,
placeholder: 'Escreva o conteúdo da página aqui...',
tabsize: 2,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture', 'video']],
['view', ['fullscreen', 'codeview', 'help']]
]
});
// Gerar slug automaticamente a partir do título
document.getElementById('title').addEventListener('keyup', function() {
let text = this.value.toLowerCase()
.normalize('NFD').replace(/[\u0300-\u036f]/g, "") // Remove acentos
.replace(/[^\w ]+/g, '')
.replace(/ +/g, '-');
document.getElementById('slug').value = text;
});
});
</script>
@endpush
+176
View File
@@ -0,0 +1,176 @@
@extends('layouts.admin')
@section('title', 'Editar Página')
@section('content')
@php
$managedPages = [
'contato' => ['label' => 'Contato', 'route' => route('admin.contacts.index'), 'section' => 'Mensagens de Contato'],
'faq' => ['label' => 'FAQ', 'route' => route('admin.faqs.index'), 'section' => 'Gerenciamento de FAQ'],
'downloads' => ['label' => 'Downloads', 'route' => route('admin.downloads.index'), 'section' => 'Gerenciamento de Downloads'],
'produtos' => ['label' => 'Produtos', 'route' => '#', 'section' => 'Módulo de Produtos'],
'servicos' => ['label' => 'Serviços', 'route' => '#', 'section' => 'Módulo de Serviços'],
];
$isManaged = isset($managedPages[$page->slug]);
@endphp
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar Página: {{ $page->title }}</h1>
<a href="{{ route('admin.pages.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
@if($isManaged)
<div class="alert alert-warning border-0 shadow-sm mb-4">
<div class="d-flex align-items-start">
<i class="bi bi-exclamation-triangle me-3 mt-1"></i>
<div>
<h5 class="alert-heading mb-1">Página com conteúdo dinâmico</h5>
<p class="mb-2">
O conteúdo desta página (<strong>{{ $managedPages[$page->slug]['label'] }}</strong>) é gerado dinamicamente pelo sistema e <strong>não deve ser editado manualmente</strong> por aqui. As informações exibidas nela são controladas pela seção <strong>{{ $managedPages[$page->slug]['section'] }}</strong> no painel administrativo.
</p>
@if($managedPages[$page->slug]['route'] !== '#')
<a href="{{ $managedPages[$page->slug]['route'] }}" class="btn btn-sm btn-warning">
<i class="bi bi-box-arrow-up-right me-1"></i> Ir para {{ $managedPages[$page->slug]['section'] }}
</a>
@endif
<p class="small text-muted mt-2 mb-0">
<i class="bi bi-info-circle me-1"></i> Você ainda pode ajustar o título, slug, SEO e o status da página abaixo, mas o conteúdo principal será sobrescrito pelo módulo correspondente.
</p>
</div>
</div>
</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex justify-content-between align-items-center">
<h6 class="m-0 font-weight-bold text-primary">Editar Conteúdo</h6>
<a href="{{ url($page->slug == 'index' ? '/' : $page->slug) }}" target="_blank" class="btn btn-sm btn-info">
<i class="bi bi-box-arrow-up-right"></i> Visualizar no Site
</a>
</div>
<div class="card-body">
<form action="{{ route('admin.pages.update', $page) }}" method="POST">
@csrf
@method('PUT')
<div class="row">
<div class="col-md-8">
<div class="form-group mb-3">
<label class="font-weight-bold">Título da Página</label>
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror" value="{{ old('title', $page->title) }}" required>
@error('title') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3 {{ $isManaged ? 'opacity-50' : '' }}">
<label class="font-weight-bold">
Conteúdo (HTML)
@if($isManaged)
<span class="badge badge-warning ml-1"><i class="bi bi-lock me-1"></i>Gerenciado pelo sistema</span>
@endif
</label>
<textarea name="content" id="editor" class="form-control @error('content') is-invalid @enderror" rows="20" {{ $isManaged ? 'disabled' : '' }}>{{ old('content', $page->content) }}</textarea>
@error('content') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-4">
<div class="form-group mb-3">
<label class="font-weight-bold">Slug (URL amigável)</label>
<input type="text" name="slug" class="form-control @error('slug') is-invalid @enderror" value="{{ old('slug', $page->slug) }}" {{ in_array($page->slug, ['index', 'about', 'produtos', 'servicos', 'downloads', 'contato', 'faq']) ? 'readonly' : 'required' }}>
<small class="text-muted">As páginas principais do sistema não podem ter o slug alterado.</small>
@error('slug') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Meta Description (SEO)</label>
<textarea name="meta_description" class="form-control @error('meta_description') is-invalid @enderror" rows="3">{{ old('meta_description', $page->meta_description) }}</textarea>
@error('meta_description') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ old('active', $page->active) ? 'selected' : '' }}>Ativa (Visível)</option>
<option value="0" {{ old('active', $page->active) ? '' : 'selected' }}>Inativa (Oculta)</option>
</select>
</div>
<hr>
<h6 class="font-weight-bold text-primary mb-3"><i class="bi bi-search me-1"></i> Configurações Avançadas de SEO</h6>
<div class="form-group mb-3">
<label class="small font-weight-bold">Palavras-chave (Keywords)</label>
<input type="text" name="meta_keywords" class="form-control form-control-sm" value="{{ old('meta_keywords', $page->meta_keywords) }}" placeholder="computador, manutenção, vendas">
</div>
<div class="form-group mb-3">
<label class="small font-weight-bold">URL Canônica</label>
<input type="text" name="canonical_url" class="form-control form-control-sm" value="{{ old('canonical_url', $page->canonical_url) }}" placeholder="https://exemplo.com/pagina">
</div>
<div class="bg-light p-3 rounded border">
<h6 class="small font-weight-bold mb-2">Redes Sociais (Open Graph)</h6>
<div class="form-group mb-2">
<label class="x-small">Título OG</label>
<input type="text" name="og_title" class="form-control form-control-sm" value="{{ old('og_title', $page->og_title) }}">
</div>
<div class="form-group mb-2">
<label class="x-small">Descrição OG</label>
<textarea name="og_description" class="form-control form-control-sm" rows="2">{{ old('og_description', $page->og_description) }}</textarea>
</div>
<div class="form-group mb-0">
<label class="x-small">URL da Imagem OG</label>
<input type="text" name="og_image" class="form-control form-control-sm" value="{{ old('og_image', $page->og_image) }}">
</div>
</div>
</div>
</div>
<hr>
<button type="submit" class="btn btn-primary btn-block py-3 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Salvar Alterações
</button>
</form>
</div>
</div>
@endsection
@push('css')
<!-- Incluindo o editor Summernote para facilitar a edição HTML -->
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.css" rel="stylesheet">
@endpush
@push('js')
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.js"></script>
<script>
$(document).ready(function() {
@if($isManaged)
// Disable editor for system-managed pages
$('#editor').summernote({
height: 400,
disabled: true,
placeholder: 'O conteúdo desta página é gerenciado automaticamente pelo sistema.',
tabsize: 2,
toolbar: []
});
@else
$('#editor').summernote({
height: 400,
placeholder: 'Escreva o conteúdo da página aqui...',
tabsize: 2,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture', 'video']],
['view', ['fullscreen', 'codeview', 'help']]
]
});
@endif
});
</script>
@endpush
+75
View File
@@ -0,0 +1,75 @@
@extends('layouts.admin')
@section('title', 'Gerenciar Páginas')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Páginas Institucionais</h1>
<a href="{{ route('admin.pages.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Nova Página
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm">{{ session('success') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Páginas</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Título</th>
<th>Slug (URL)</th>
<th>Status</th>
<th>Última Atualização</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($pages as $page)
@php
$managedSlugs = ['contato', 'faq', 'downloads', 'produtos', 'servicos'];
$isManaged = in_array($page->slug, $managedSlugs);
@endphp
<tr class="{{ $isManaged ? 'table-warning' : '' }}">
<td>
{{ $page->title }}
@if($isManaged)
<span class="badge badge-warning ml-1" title="Conteúdo gerenciado pelo sistema"><i class="bi bi-lock"></i> Sistema</span>
@endif
</td>
<td><code>/{{ $page->slug }}</code></td>
<td>
<span class="badge badge-{{ $page->active ? 'success' : 'secondary' }}">
{{ $page->active ? 'Ativa' : 'Inativa' }}
</span>
</td>
<td>{{ $page->updated_at->format('d/m/Y H:i') }}</td>
<td>
<a href="{{ route('admin.pages.edit', $page) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i> Editar
</a>
<a href="{{ url($page->slug == 'index' ? '/' : $page->slug) }}" target="_blank" class="btn btn-sm btn-info">
<i class="bi bi-eye"></i> Ver
</a>
<form action="{{ route('admin.pages.destroy', $page) }}" method="POST" style="display: inline;">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Tem certeza que deseja excluir esta página?')">
<i class="bi bi-trash"></i> Excluir
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endsection
+207
View File
@@ -0,0 +1,207 @@
@extends('layouts.admin')
@section('title', 'Configurações do Site')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Configurações Gerais</h1>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm mb-4">{{ session('success') }}</div>
@endif
<form action="{{ route('admin.settings.update') }}" method="POST">
@csrf
<!-- Nav Tabs -->
<ul class="nav nav-tabs mb-4" id="settingsTabs" role="tablist">
<li class="nav-item">
<a class="nav-link active font-weight-bold" id="company-tab" data-toggle="tab" href="#company" role="tab"><i class="bi bi-building me-1"></i> Dados da Empresa</a>
</li>
<li class="nav-item">
<a class="nav-link font-weight-bold" id="seo-tab" data-toggle="tab" href="#seo" role="tab"><i class="bi bi-globe me-1"></i> SEO Global</a>
</li>
<li class="nav-item">
<a class="nav-link font-weight-bold" id="scripts-tab" data-toggle="tab" href="#scripts" role="tab"><i class="bi bi-code-slash me-1"></i> Scripts e Integrações</a>
</li>
<li class="nav-item">
<a class="nav-link font-weight-bold" id="marketing-settings-tab" data-toggle="tab" href="#marketing-settings" role="tab"><i class="bi bi-megaphone me-1"></i> Marketing</a>
</li>
</ul>
<!-- Tab Content -->
<div class="tab-content" id="settingsTabsContent">
<!-- Aba Dados da Empresa -->
<div class="tab-pane fade show active" id="company" role="tabpanel">
<div class="row">
<div class="col-lg-12">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações Institucionais</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Nome da Empresa</label>
<input type="text" name="company_name" class="form-control" value="{{ \App\Models\Setting::get('company_name', 'Syspanel') }}">
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Slogan da Empresa</label>
<input type="text" name="company_slogan" class="form-control" value="{{ \App\Models\Setting::get('company_slogan', 'Sua parceira em tecnologia e manutenção de informática.') }}">
<small class="text-muted">Aparece no rodapé e em outros locais</small>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">CNPJ</label>
<input type="text" name="company_cnpj" class="form-control" value="{{ \App\Models\Setting::get('company_cnpj') }}" placeholder="00.000.000/0000-00">
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">E-mail de Contato Principal</label>
<input type="email" name="company_email" class="form-control" value="{{ \App\Models\Setting::get('company_email') }}">
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Telefone / WhatsApp</label>
<input type="text" name="company_phone" class="form-control" value="{{ \App\Models\Setting::get('company_phone') }}">
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label class="font-weight-bold">Endereço Completo</label>
<textarea name="company_address" class="form-control" rows="2">{{ \App\Models\Setting::get('company_address') }}</textarea>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Horário de Atendimento</label>
<input type="text" name="company_hours" class="form-control" value="{{ \App\Models\Setting::get('company_hours') }}" placeholder="Seg a Sex: 08h às 18h">
</div>
<hr>
<h6 class="font-weight-bold text-dark mb-3">Redes Sociais (Links completos)</h6>
<div class="form-group mb-2">
<div class="input-group">
<div class="input-group-prepend"><span class="input-group-text"><i class="bi bi-instagram"></i></span></div>
<input type="text" name="company_instagram" class="form-control" value="{{ \App\Models\Setting::get('company_instagram') }}" placeholder="https://instagram.com/perfil">
</div>
</div>
<div class="form-group mb-2">
<div class="input-group">
<div class="input-group-prepend"><span class="input-group-text"><i class="bi bi-facebook"></i></span></div>
<input type="text" name="company_facebook" class="form-control" value="{{ \App\Models\Setting::get('company_facebook') }}" placeholder="https://facebook.com/perfil">
</div>
</div>
<div class="form-group mb-0">
<div class="input-group">
<div class="input-group-prepend"><span class="input-group-text"><i class="bi bi-linkedin"></i></span></div>
<input type="text" name="company_linkedin" class="form-control" value="{{ \App\Models\Setting::get('company_linkedin') }}" placeholder="https://linkedin.com/company/perfil">
</div>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-12">
<h6 class="font-weight-bold text-dark mb-3"><i class="bi bi-geo-alt me-1"></i> Mapa de Localização</h6>
<div class="form-group mb-0">
<label class="font-weight-bold">Iframe do Google Maps</label>
<textarea name="company_map_iframe" class="form-control" rows="4" placeholder="Cole aqui o código iframe do Google Maps...">{{ \App\Models\Setting::get('company_map_iframe') }}</textarea>
<small class="text-muted">Vá no Google Maps, compartilhe o local e selecione "Incorporar mapa" para obter o código iframe. Aparece na página de Contato.</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Aba SEO Global -->
<div class="tab-pane fade" id="seo" role="tabpanel">
<div class="row">
<div class="col-lg-12">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Configurações de Buscadores</h6>
</div>
<div class="card-body">
<div class="form-group mb-3">
<label class="font-weight-bold">Título do Site (Sufixo)</label>
<input type="text" name="seo_title_suffix" class="form-control" value="{{ \App\Models\Setting::get('seo_title_suffix', ' - Syspanel') }}">
<small class="text-muted">Ex: "Início - Syspanel"</small>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição Meta Padrão</label>
<textarea name="seo_description_default" class="form-control" rows="3">{{ \App\Models\Setting::get('seo_description_default') }}</textarea>
</div>
<div class="form-group mb-0">
<label class="font-weight-bold">Imagem OG Padrão (URL)</label>
<input type="text" name="seo_og_image_default" class="form-control" value="{{ \App\Models\Setting::get('seo_og_image_default') }}">
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Aba Scripts -->
<div class="tab-pane fade" id="scripts" role="tabpanel">
<div class="row">
<div class="col-lg-12">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Integrações e Código</h6>
</div>
<div class="card-body">
<div class="form-group mb-3">
<label class="font-weight-bold">Google Analytics (Tag ID)</label>
<input type="text" name="scripts_google_analytics" class="form-control" value="{{ \App\Models\Setting::get('scripts_google_analytics') }}" placeholder="G-XXXXXXXXXX">
</div>
<div class="form-group mb-0">
<label class="font-weight-bold">Scripts Adicionais no &lt;head&gt;</label>
<textarea name="scripts_head_custom" class="form-control" rows="6" placeholder="Ex: Meta-tags de verificação, CSS customizado">{{ \App\Models\Setting::get('scripts_head_custom') }}</textarea>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Aba Marketing -->
<div class="tab-pane fade" id="marketing-settings" role="tabpanel">
<div class="row">
<div class="col-lg-12">
<div class="card shadow mb-4 border-left-warning">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-warning">Textos de Divulgação (WhatsApp / Redes Sociais)</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="form-group mb-4">
<label class="font-weight-bold text-success"><i class="bi bi-whatsapp me-1"></i> Texto para Produtos</label>
<textarea name="marketing_product_text" class="form-control" rows="4">{{ \App\Models\Setting::get('marketing_product_text', 'Confira este produto incrível: {name} por apenas R$ {price}. Veja mais detalhes aqui: {link}') }}</textarea>
<small class="text-muted">Use as tags: <strong>{name}</strong> para o nome, <strong>{price}</strong> para o preço e <strong>{link}</strong> para a URL do produto.</small>
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-4">
<label class="font-weight-bold text-primary"><i class="bi bi-bell me-1"></i> Texto para Serviços</label>
<textarea name="marketing_service_text" class="form-control" rows="4">{{ \App\Models\Setting::get('marketing_service_text', 'Precisa de {name}? Nós podemos te ajudar! Confira nossos serviços aqui: {link}') }}</textarea>
<small class="text-muted">Use as tags: <strong>{name}</strong> para o nome e <strong>{link}</strong> para a URL da página de serviços.</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-body text-right">
<button type="submit" class="btn btn-primary px-5 py-2 fw-bold">
<i class="bi bi-floppy me-1"></i> Salvar Todas as Configurações
</button>
</div>
</div>
</form>
@endsection
+36
View File
@@ -0,0 +1,36 @@
@extends('layouts.admin')
@section('title', 'Novo Assunto')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Novo Assunto</h1>
<a href="{{ route('admin.subjects.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Criar Assunto para Contato</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.subjects.store') }}" method="POST">
@csrf
<div class="form-group mb-4">
<label class="font-weight-bold">Nome do Assunto</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name') }}" placeholder="Ex: Suporte Técnico, Vendas..." required>
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<button type="submit" class="btn btn-primary btn-block py-2 fw-bold shadow-sm">
<i class="bi bi-check-lg me-1"></i> Criar Assunto
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
+46
View File
@@ -0,0 +1,46 @@
@extends('layouts.admin')
@section('title', 'Editar Assunto')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar Assunto</h1>
<a href="{{ route('admin.subjects.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Assunto: {{ $subject->name }}</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.subjects.update', $subject) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group mb-3">
<label class="font-weight-bold">Nome do Assunto</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name', $subject->name) }}" required>
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-4">
<label class="font-weight-bold">Status</label>
<select name="active" class="form-control">
<option value="1" {{ old('active', $subject->active) ? 'selected' : '' }}>Ativo (Visível no site)</option>
<option value="0" {{ old('active', $subject->active) ? '' : 'selected' }}>Inativo (Oculto no site)</option>
</select>
</div>
<button type="submit" class="btn btn-primary btn-block py-2 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Salvar Alterações
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
+65
View File
@@ -0,0 +1,65 @@
@extends('layouts.admin')
@section('title', 'Assuntos de Contato')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Assuntos</h1>
<a href="{{ route('admin.subjects.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Novo Assunto
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm">{{ session('success') }}</div>
@endif
@if(session('error'))
<div class="alert alert-danger border-0 shadow-sm">{{ session('error') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Assuntos</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Nome</th>
<th>Status</th>
<th>Mensagens</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($subjects as $subject)
<tr>
<td>{{ $subject->name }}</td>
<td>
<span class="badge badge-{{ $subject->active ? 'success' : 'secondary' }}">
{{ $subject->active ? 'Ativo' : 'Inativo' }}
</span>
</td>
<td>{{ $subject->messages_count ?? $subject->messages()->count() }}</td>
<td>
<a href="{{ route('admin.subjects.edit', $subject) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i>
</a>
<form action="{{ route('admin.subjects.destroy', $subject) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Tem certeza que deseja excluir este assunto?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endsection
+52
View File
@@ -0,0 +1,52 @@
@extends('layouts.admin')
@section('title', 'Novo Tipo de Usuário')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Novo Tipo de Usuário</h1>
<a href="{{ route('admin.user-types.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Criar Tipo de Usuário</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.user-types.store') }}" method="POST">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">Nome do Tipo</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name') }}" required placeholder="Ex: Editor, Moderador, Visualizador">
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
<small class="text-muted mt-1 d-block">Este nome será usado como identificador do tipo de usuário.</small>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição</label>
<textarea name="description" class="form-control @error('description') is-invalid @enderror" rows="3" placeholder="Descreva o que este tipo de usuário pode fazer">{{ old('description') }}</textarea>
@error('description') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-4">
<div class="custom-control custom-switch">
<input type="checkbox" name="is_admin" class="custom-control-input" id="is_admin" {{ old('is_admin') ? 'checked' : '' }}>
<label class="custom-control-label font-weight-bold text-danger" for="is_admin">Tipo Administrador</label>
<small class="d-block text-muted">Quando ativado, usuários deste tipo terão acesso total ao sistema (todas as permissões).</small>
</div>
</div>
<button type="submit" class="btn btn-primary btn-block py-2 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Criar Tipo
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
+57
View File
@@ -0,0 +1,57 @@
@extends('layouts.admin')
@section('title', 'Editar Tipo de Usuário')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar Tipo: {{ $userType->name }}</h1>
<a href="{{ route('admin.user-types.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Editar Tipo de Usuário</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.user-types.update', $userType) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group mb-3">
<label class="font-weight-bold">Nome do Tipo</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name', $userType->name) }}" required>
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
@if($userType->is_protected)
<small class="text-warning mt-1 d-block"><i class="bi bi-exclamation-triangle"></i> Este é um tipo protegido. Alterar o nome afetará todos os usuários deste tipo.</small>
@else
<small class="text-muted mt-1 d-block">Alterar o nome atualizará automaticamente todos os usuários deste tipo.</small>
@endif
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Descrição</label>
<textarea name="description" class="form-control @error('description') is-invalid @enderror" rows="3">{{ old('description', $userType->description) }}</textarea>
@error('description') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-4">
<div class="custom-control custom-switch">
<input type="checkbox" name="is_admin" class="custom-control-input" id="is_admin" {{ old('is_admin', $userType->is_admin) ? 'checked' : '' }}>
<label class="custom-control-label font-weight-bold text-danger" for="is_admin">Tipo Administrador</label>
<small class="d-block text-muted">Quando ativado, usuários deste tipo terão acesso total ao sistema (todas as permissões).</small>
</div>
</div>
<button type="submit" class="btn btn-primary btn-block py-2 fw-bold shadow-sm">
<i class="bi bi-floppy me-1"></i> Salvar Alterações
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
+83
View File
@@ -0,0 +1,83 @@
@extends('layouts.admin')
@section('title', 'Tipos de Usuário')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Tipos de Usuário</h1>
<a href="{{ route('admin.user-types.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Novo Tipo
</a>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm">{{ session('success') }}</div>
@endif
@if(session('error'))
<div class="alert alert-danger border-0 shadow-sm">{{ session('error') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Tipos de Usuário</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Nome</th>
<th>Descrição</th>
<th>Administrador</th>
<th>Protegido</th>
<th>Usuários</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($userTypes as $type)
<tr>
<td>
<span class="font-weight-bold">{{ $type->name }}</span>
</td>
<td>{{ $type->description ?? '-' }}</td>
<td>
@if($type->is_admin)
<span class="badge badge-danger">Sim</span>
@else
<span class="badge badge-secondary">Não</span>
@endif
</td>
<td>
@if($type->is_protected)
<span class="badge badge-warning"><i class="bi bi-lock"></i> Sim</span>
@else
<span class="badge badge-light">Não</span>
@endif
</td>
<td>
<span class="badge badge-info">{{ $type->users_count }}</span>
</td>
<td>
<a href="{{ route('admin.user-types.edit', $type) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i>
</a>
@unless($type->is_protected)
<form action="{{ route('admin.user-types.destroy', $type) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Tem certeza que deseja excluir este tipo de usuário?')">
<i class="bi bi-trash"></i>
</button>
</form>
@endunless
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endsection
+138
View File
@@ -0,0 +1,138 @@
@extends('layouts.admin')
@section('title', 'Novo Usuário')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Novo Usuário</h1>
<a href="{{ route('admin.users.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50"></i> Voltar
</a>
</div>
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Criar Novo Cadastro</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.users.store') }}" method="POST">
@csrf
<div class="form-group mb-3">
<label class="font-weight-bold">Nome Completo</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name') }}" required placeholder="Ex: João Silva">
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">E-mail</label>
<input type="email" name="email" class="form-control @error('email') is-invalid @enderror" value="{{ old('email') }}" required placeholder="email@exemplo.com">
@error('email') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Senha Inicial</label>
<div class="input-group">
<input type="password" name="password" class="form-control @error('password') is-invalid @enderror" required placeholder="Mínimo 8 caracteres">
<div class="input-group-append">
<button class="btn btn-outline-secondary toggle-password" type="button">
<i class="bi bi-eye"></i>
</button>
</div>
@error('password') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="form-group mb-3">
<div class="d-flex justify-content-between align-items-center">
<label class="font-weight-bold">Tipo de Usuário</label>
<a href="{{ route('admin.user-types.index') }}" class="text-small text-decoration-none"><i class="bi bi-gear"></i> Gerenciar Tipos</a>
</div>
<select name="user_type" id="user_type" class="form-control @error('user_type') is-invalid @enderror" required>
@foreach($userTypes as $type)
<option value="{{ $type->name }}" {{ old('user_type') === $type->name ? 'selected' : '' }}>{{ $type->name }}@if($type->is_admin) (Admin)@endif</option>
@endforeach
</select>
@error('user_type') <div class="invalid-feedback">{{ $message }}</div> @enderror
<small class="text-muted mt-1 d-block">Tipos marcados como Admin têm acesso total ao sistema. Os demais têm acesso apenas às seções permitidas abaixo.</small>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Empresa</label>
<input type="text" name="company" class="form-control @error('company') is-invalid @enderror" value="{{ old('company') }}" placeholder="Opcional">
@error('company') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="font-weight-bold">Site</label>
<input type="text" name="website" class="form-control @error('website') is-invalid @enderror" value="{{ old('website') }}" placeholder="Opcional">
@error('website') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="col-md-6 mb-3">
<label class="font-weight-bold">WhatsApp</label>
<input type="text" name="whatsapp" class="form-control @error('whatsapp') is-invalid @enderror" value="{{ old('whatsapp') }}" placeholder="Opcional">
@error('whatsapp') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<!-- Permissions Section -->
<div id="permissions-section">
<hr class="my-4">
<h6 class="font-weight-bold text-primary mb-3"><i class="bi bi-shield-check me-1"></i> Permissões de Acesso</h6>
<p class="text-muted small mb-3">Selecione quais seções do sistema este usuário poderá acessar. Esta configuração se aplica apenas a usuários do tipo <strong>User</strong>.</p>
<div class="row">
@foreach($availablePermissions as $key => $label)
<div class="col-md-6 mb-2">
<div class="custom-control custom-checkbox">
<input type="checkbox" name="permissions[]" value="{{ $key }}" id="perm_{{ $key }}" class="custom-control-input permission-check" {{ in_array($key, old('permissions', [])) ? 'checked' : '' }}>
<label class="custom-control-label" for="perm_{{ $key }}">{{ $label }}</label>
</div>
</div>
@endforeach
</div>
<div class="mt-2 mb-3">
<button type="button" id="select-all-perms" class="btn btn-sm btn-outline-primary me-2">Selecionar Todas</button>
<button type="button" id="deselect-all-perms" class="btn btn-sm btn-outline-secondary">Desmarcar Todas</button>
</div>
</div>
<button type="submit" class="btn btn-primary btn-block py-2 fw-bold shadow-sm">
<i class="bi bi-plus-lg me-1"></i> Cadastrar Usuário
</button>
</form>
</div>
</div>
</div>
</div>
@push('js')
<script>
$(document).ready(function() {
function togglePermissions() {
var userType = $('#user_type').val();
if (userType === 'Admin') {
$('#permissions-section').slideUp();
} else {
$('#permissions-section').slideDown();
}
}
$('#user_type').change(togglePermissions);
togglePermissions();
$('#select-all-perms').click(function() {
$('.permission-check').prop('checked', true);
});
$('#deselect-all-perms').click(function() {
$('.permission-check').prop('checked', false);
});
});
</script>
@endpush
@endsection
+168
View File
@@ -0,0 +1,168 @@
@extends('layouts.admin')
@section('title', 'Editar Usuário')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Editar Usuário: {{ $user->name }}</h1>
<a href="{{ route('admin.users.index') }}" class="btn btn-sm btn-secondary shadow-sm">
<i class="bi bi-arrow-left text-white-50 me-1"></i> Voltar
</a>
</div>
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Informações de {{ $user->name }}</h6>
</div>
<div class="card-body">
<form action="{{ route('admin.users.update', $user) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group mb-3">
<label class="font-weight-bold">Nome</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name', $user->name) }}" required>
@error('name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">E-mail (Não editável)</label>
<input type="email" class="form-control bg-light" value="{{ $user->email }}" readonly>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Data de Confirmação do Cadastro</label>
<div class="input-group">
<span class="input-group-text bg-light"><i class="bi bi-calendar-check text-success"></i></span>
<input type="text" class="form-control bg-light"
value="{{ $user->email_verified_at ? $user->email_verified_at->format('d/m/Y H:i:s') : 'Pendente de Confirmação' }}"
readonly>
</div>
@if(!$user->email_verified_at)
<small class="text-danger mt-1 d-block"><i class="bi bi-exclamation-triangle"></i> Este usuário ainda não confirmou o e-mail.</small>
@endif
</div>
<div class="form-group mb-3">
<div class="d-flex justify-content-between align-items-center">
<label class="font-weight-bold">Tipo de Usuário</label>
<a href="{{ route('admin.user-types.index') }}" class="text-small text-decoration-none"><i class="bi bi-gear"></i> Gerenciar Tipos</a>
</div>
<select name="user_type" id="user_type" class="form-control @error('user_type') is-invalid @enderror" required>
@foreach($userTypes as $type)
<option value="{{ $type->name }}" {{ old('user_type', $user->user_type) === $type->name ? 'selected' : '' }}>{{ $type->name }}@if($type->is_admin) (Admin)@endif</option>
@endforeach
</select>
@error('user_type') <div class="invalid-feedback">{{ $message }}</div> @enderror
<small class="text-muted mt-1 d-block">Tipos marcados como Admin têm acesso total ao sistema. Os demais têm acesso apenas às seções permitidas abaixo.</small>
</div>
<div class="form-group mb-3">
<label class="font-weight-bold">Empresa</label>
<input type="text" name="company" class="form-control @error('company') is-invalid @enderror" value="{{ old('company', $user->company) }}">
@error('company') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="font-weight-bold">Site</label>
<input type="text" name="website" class="form-control @error('website') is-invalid @enderror" value="{{ old('website', $user->website) }}">
@error('website') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="col-md-6 mb-3">
<label class="font-weight-bold">WhatsApp</label>
<input type="text" name="whatsapp" class="form-control @error('whatsapp') is-invalid @enderror" value="{{ old('whatsapp', $user->whatsapp) }}">
@error('whatsapp') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<hr class="my-4">
<h6 class="font-weight-bold text-danger mb-3"><i class="bi bi-lock me-1"></i> Alterar Senha (Opcional)</h6>
<p class="text-muted small mb-3">Preencha os campos abaixo apenas se desejar alterar a senha deste usuário. Caso contrário, deixe-os em branco.</p>
<div class="row">
<div class="col-md-6 mb-3">
<label class="font-weight-bold">Nova Senha</label>
<div class="input-group">
<input type="password" name="password" class="form-control @error('password') is-invalid @enderror" placeholder="Mínimo 8 caracteres" autocomplete="new-password">
<div class="input-group-append">
<button class="btn btn-outline-secondary toggle-password" type="button">
<i class="bi bi-eye"></i>
</button>
</div>
@error('password') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="col-md-6 mb-3">
<label class="font-weight-bold">Confirmar Nova Senha</label>
<div class="input-group">
<input type="password" name="password_confirmation" class="form-control" placeholder="Repita a nova senha" autocomplete="new-password">
<div class="input-group-append">
<button class="btn btn-outline-secondary toggle-password" type="button">
<i class="bi bi-eye"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Permissions Section -->
<div id="permissions-section">
<hr class="my-4">
<h6 class="font-weight-bold text-primary mb-3"><i class="bi bi-shield-check me-1"></i> Permissões de Acesso</h6>
<p class="text-muted small mb-3">Selecione quais seções do sistema este usuário poderá acessar. Esta configuração se aplica apenas a usuários do tipo <strong>User</strong>.</p>
<div class="row">
@foreach($availablePermissions as $key => $label)
<div class="col-md-6 mb-2">
<div class="custom-control custom-checkbox">
<input type="checkbox" name="permissions[]" value="{{ $key }}" id="perm_{{ $key }}" class="custom-control-input permission-check" {{ in_array($key, old('permissions', $user->permissions ?? [])) ? 'checked' : '' }}>
<label class="custom-control-label" for="perm_{{ $key }}">{{ $label }}</label>
</div>
</div>
@endforeach
</div>
<div class="mt-2 mb-3">
<button type="button" id="select-all-perms" class="btn btn-sm btn-outline-primary me-2">Selecionar Todas</button>
<button type="button" id="deselect-all-perms" class="btn btn-sm btn-outline-secondary">Desmarcar Todas</button>
</div>
</div>
<button type="submit" class="btn btn-primary btn-block py-2 fw-bold shadow-sm mt-3">
<i class="bi bi-floppy me-1"></i> Salvar Alterações
</button>
</form>
</div>
</div>
</div>
</div>
@push('js')
<script>
$(document).ready(function() {
function togglePermissions() {
var userType = $('#user_type').val();
if (userType === 'Admin') {
$('#permissions-section').slideUp();
} else {
$('#permissions-section').slideDown();
}
}
$('#user_type').change(togglePermissions);
togglePermissions();
$('#select-all-perms').click(function() {
$('.permission-check').prop('checked', true);
});
$('#deselect-all-perms').click(function() {
$('.permission-check').prop('checked', false);
});
});
</script>
@endpush
@endsection
+100
View File
@@ -0,0 +1,100 @@
@extends('layouts.admin')
@section('title', 'Gerenciar Cadastros')
@section('content')
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Administração de Usuários</h1>
<div>
<a href="{{ route('admin.user-types.index') }}" class="btn btn-sm btn-outline-secondary shadow-sm me-2">
<i class="bi bi-tags"></i> Tipos de Usuário
</a>
<a href="{{ route('admin.users.create') }}" class="btn btn-sm btn-primary shadow-sm">
<i class="bi bi-plus-lg text-white-50"></i> Novo Usuário
</a>
</div>
</div>
@if(session('success'))
<div class="alert alert-success border-0 shadow-sm">{{ session('success') }}</div>
@endif
@if(session('error'))
<div class="alert alert-danger border-0 shadow-sm">{{ session('error') }}</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lista de Usuários</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" width="100%" cellspacing="0">
<thead>
<tr>
<th>Nome</th>
<th>E-mail</th>
<th>Tipo</th>
<th>Permissões</th>
<th>Empresa</th>
<th>WhatsApp</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
@foreach($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
@php
$typeIsAdmin = false;
foreach($userTypes as $ut) {
if ($ut->name === $user->user_type && $ut->is_admin) {
$typeIsAdmin = true;
break;
}
}
@endphp
<span class="badge badge-{{ $typeIsAdmin ? 'danger' : 'primary' }}">
{{ $user->user_type }}
</span>
</td>
<td>
@if($user->isAdmin())
<span class="badge badge-success">Acesso Total</span>
@elseif(is_array($user->permissions) && count($user->permissions) > 0)
@foreach($user->permissions as $perm)
@if(isset($availablePermissions[$perm]))
<span class="badge badge-info me-1 mb-1" title="{{ $availablePermissions[$perm] }}">{{ $availablePermissions[$perm] }}</span>
@endif
@endforeach
@else
<span class="text-muted small">Nenhuma permissão</span>
@endif
</td>
<td>{{ $user->company ?? '-' }}</td>
<td>{{ $user->whatsapp ?? '-' }}</td>
<td>
<a href="{{ route('admin.users.edit', $user) }}" class="btn btn-sm btn-primary">
<i class="bi bi-pencil"></i>
</a>
<form action="{{ route('admin.users.destroy', $user) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Tem certeza que deseja excluir este usuário?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-4">
{{ $users->links() }}
</div>
</div>
</div>
@endsection