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

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

175 lines
6.1 KiB
PHP
Executable File

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\ContactSubject;
use App\Models\ContactMessage;
use App\Models\Page;
use App\Models\Faq;
use App\Models\Download;
use App\Models\Gallery;
use App\Models\GalleryCategory;
use App\Models\News;
use App\Models\Banner;
use App\Models\User;
use App\Notifications\NewContactMessageNotification;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Redirect;
class PageController extends Controller
{
public function index()
{
$page = Page::where('slug', 'index')->where('active', true)->firstOrFail();
$banners = Banner::where('active', true)->orderBy('order')->get();
return view('index', compact('page', 'banners'));
}
public function about()
{
$page = Page::where('slug', 'about')->where('active', true)->firstOrFail();
return view('about', compact('page'));
}
// Note: produtos() is now handled by the Products module (ProductPageController)
// Note: servicos() is now handled by the Services module (ServicePageController)
public function assistentesDigitaisIA()
{
$page = Page::where('slug', 'assistentes-digitais-com-ia')->where('active', true)->firstOrFail();
return view('assistentes-digitais-ia', compact('page'));
}
public function servidoresLinux()
{
$page = Page::where('slug', 'linux-servers')->where('active', true)->firstOrFail();
return view('servidores-linux', compact('page'));
}
public function erp()
{
$page = Page::where('slug', 'erp')->where('active', true)->firstOrFail();
return view('erp', compact('page'));
}
public function fluxoDeCaixaPro()
{
$page = Page::where('slug', 'fluxo-de-caixa-pro')->where('active', true)->firstOrFail();
return view('fluxo-de-caixa-pro', compact('page'));
}
public function downloads()
{
$page = Page::where('slug', 'downloads')->where('active', true)->firstOrFail();
$downloads = Download::where('active', true)->latest()->get();
return view('downloads', compact('downloads', 'page'));
}
public function downloadFile(Download $download)
{
// Only allow download if the download is active
if (!$download->active) {
abort(404, 'Download não encontrado.');
}
$download->increment('download_count');
return response()->download(storage_path('app/public/' . $download->file_path));
}
public function faq()
{
$page = Page::where('slug', 'faq')->where('active', true)->firstOrFail();
$faqs = Faq::where('active', true)->orderBy('order')->get();
return view('faq', compact('faqs', 'page'));
}
public function galleryCategory($slug)
{
$category = GalleryCategory::where('slug', $slug)->where('active', true)->firstOrFail();
$galleries = Gallery::where('active', true)->where('category_id', $category->id)->with('images')->withCount('images')->orderBy('title')->paginate(12);
return view('gallery-category', compact('category', 'galleries'));
}
public function gallery($slug)
{
$gallery = Gallery::where('slug', $slug)->where('active', true)->with('images')->firstOrFail();
return view('gallery-show', compact('gallery'));
}
public function newsIndex()
{
$newsList = News::published()->latest('published_at')->latest()->paginate(9);
return view('news-index', compact('newsList'));
}
public function newsShow($slug)
{
$news = News::where('slug', $slug)->published()->with('images')->firstOrFail();
return view('news-show', compact('news'));
}
/**
* Show a custom dynamic page.
*/
public function show($slug)
{
$page = Page::where('slug', $slug)->where('active', true)->firstOrFail();
return view('page', compact('page'));
}
public function contato()
{
$page = Page::where('slug', 'contato')->where('active', true)->firstOrFail();
$subjects = ContactSubject::where('active', true)->orderBy('name')->get();
return view('contato', compact('subjects', 'page'));
}
public function sendContact(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|max:255',
'subject_id' => 'required|exists:contact_subjects,id',
'message' => 'required|string|min:10',
'whatsapp' => 'nullable|string|max:20|regex:/^[\d\s\(\)\+\-]{10,20}$/',
'company' => 'nullable|string|max:255',
'website' => 'nullable|string|max:255|regex:/^https?:\/\/.+\..+$/i',
'captcha' => 'required|numeric',
], [
'whatsapp.regex' => 'O formato do WhatsApp é inválido.',
'website.regex' => 'O site deve começar com http:// ou https:// e ter um formato válido.',
]);
// Captcha validation with timing-safe comparison
if (!hash_equals((string) session('captcha_result'), (string) $request->captcha)) {
return back()->withErrors(['captcha' => 'O resultado da soma está incorreto.'])->withInput();
}
// Create contact message with explicit fields
$contact = ContactMessage::create([
'name' => $request->name,
'email' => $request->email,
'company' => $request->company,
'website' => $request->website,
'whatsapp' => $request->whatsapp,
'subject_id' => $request->subject_id,
'message' => $request->message,
]);
// Notify administrators
$admins = User::where('user_type', 'Admin')->get();
Notification::send($admins, new NewContactMessageNotification($contact));
return Redirect::route('contato')->with('success', 'Sua mensagem foi enviada com sucesso! Em breve entraremos em contato.');
}
public function politicaPrivacidade()
{
$page = Page::where('slug', 'politica-privacidade')->where('active', true)->first();
return view('politica-privacidade', compact('page'));
}
}