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:
Executable
+174
@@ -0,0 +1,174 @@
|
||||
<?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'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user