Your IP : 216.73.216.79


Current Path : /var/www/html/reddsis/app/Http/Controllers/Backend/
Upload File :
Current File : /var/www/html/reddsis/app/Http/Controllers/Backend/FrontendPageController.php

<?php

namespace App\Http\Controllers\Backend;

use App\Http\Controllers\Controller;
use App\Models\Backend\FrontendPage;
use App\Models\Backend\FrontendSite;
use App\Models\Backend\FrontendComponent;
use App\Services\BladeSyncService;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

class FrontendPageController extends Controller
{
    public function index(Request $request)
    {
        $siteId = $request->get('site_id');
        $search = $request->get('search');
        $sites = FrontendSite::orderBy('name')->pluck('name', 'id');

        $pages = FrontendPage::with('site')
            ->when($siteId, fn($q) => $q->where('site_fk', $siteId))
            ->when($search, fn($q) => $q->where(function($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('slug', 'like', "%{$search}%");
            }))
            ->orderByDesc('status')
            ->orderBy('sort_order')
            ->paginate(10);

        return view('backend.module.frontendSite.page.index', ['pages' => $pages, 'sites' => $sites, 'siteId' => $siteId, 'search' => $search]);
    }

    public function create(Request $request)
    {
        $sites = FrontendSite::orderBy('name')->pluck('name', 'id');
        $components = FrontendComponent::where('status', true)->orderBy('category')->orderBy('name')->get();
        $selectedSiteId = $request->get('site_id');

        return view('backend.module.frontendSite.page.create', ['sites' => $sites, 'components' => $components, 'selectedSiteId' => $selectedSiteId]);
    }

    public function store(Request $request)
    {
        $pageId = $request->input('page_id');
        $isAjax = $request->ajax();

        $data = $request->validate([
            'site_fk' => 'required|integer|exists:frontend_sites,id',
            'name' => $isAjax ? 'nullable|string|max:255' : 'required|string|max:255',
            'slug' => $isAjax
                ? 'nullable|string|max:255'
                : 'required|string|max:255' . ($pageId ? '' : '|unique:frontend_pages,slug,NULL,id,site_fk,' . $request->site_fk),
            'layout' => 'nullable|string',
            'entry_script' => ['nullable', 'string', function ($attribute, $value, $fail) {
                if ($value && preg_match('/\{!!\s*\$/', $value)) {
                    $fail('Entry Script cannot contain {!! $... !!} syntax. Use Page Content for component output. Entry Script is for @php logic only.');
                }
            }],
            'page_content' => 'nullable|string',
            'use_custom_layout' => 'nullable|boolean',
            'is_default' => 'nullable|boolean',
            'status' => 'nullable|boolean',
            'sort_order' => 'nullable|integer|min:0',
            'components' => 'nullable|array',
            'components.*' => 'integer|exists:frontend_components,id',
        ]);

        $data['is_default'] = $request->boolean('is_default');
        $data['status'] = $request->boolean('status');
        $data['use_custom_layout'] = $request->boolean('use_custom_layout');
        $data['sort_order'] ??= 0;

        // Resolve existing page by ID (after first AJAX save) or by slug
        if ($pageId) {
            $page = FrontendPage::findOrFail($pageId);
        } else {
            $page = !empty($data['slug'])
                ? FrontendPage::where('site_fk', $data['site_fk'])->where('slug', $data['slug'])->first()
                : null;
        }

        if ($page) {
            // Auto-unset other default pages in same site
            if ($data['is_default']) {
                FrontendPage::where('site_fk', $data['site_fk'])->where('id', '!=', $page->id)->where('is_default', true)->update(['is_default' => false]);
            }
            // AJAX modal save only updates code fields, not name/slug
            $page->update($isAjax ? Arr::except($data, ['name', 'slug']) : $data);
        } else {
            if (empty($data['name']) || empty($data['slug'])) {
                if ($isAjax) {
                    return response()->json(['message' => 'Please fill in Name and Slug before saving code.'], 422);
                }
                return back()->withInput()->withErrors(['name' => 'Please fill in Name and Slug before saving.']);
            }

            // Auto-unset other default pages in same site
            if ($data['is_default']) {
                FrontendPage::where('site_fk', $data['site_fk'])->where('is_default', true)->update(['is_default' => false]);
            }
            $page = FrontendPage::create($data);

            // Auto-set default untuk rekod pertama site ni
            if (FrontendPage::where('site_fk', $data['site_fk'])->count() === 1) {
                $page->update(['is_default' => true]);
            }
        }

        app(BladeSyncService::class)->syncAll();

        $page->components()->detach();
        if ($request->has('components')) {
            $sort = 0;
            foreach ($request->components as $compId) {
                $page->components()->attach($compId, ['sort' => $sort++]);
            }
        }

        if ($isAjax) {
            return response()->json(['message' => 'Code updated successfully!', 'page_id' => $page->id]);
        }

        if (!$request->filled('entry_script') && !$request->filled('page_content') && !$request->has('components')) {
            flash()->warning('Page created but no Entry Script, Page Content, or Components were provided. The page may appear empty.');
        } else {
            flash()->success('Page created successfully!');
        }
        return redirect()->route('frontend-site.pages.index', ['site_id' => $page->site_fk]);
    }

    public function edit($id)
    {
        $page = FrontendPage::with('components')->findOrFail($id);
        $sites = FrontendSite::orderBy('name')->pluck('name', 'id');
        $components = FrontendComponent::where('status', true)->orderBy('category')->orderBy('name')->get();
        $selectedIds = $page->components->pluck('id')->toArray();

        return view('backend.module.frontendSite.page.edit', ['page' => $page, 'sites' => $sites, 'components' => $components, 'selectedIds' => $selectedIds]);
    }

    public function update(Request $request, $id)
    {
        $page = FrontendPage::findOrFail($id);

        $data = $request->validate([
            'site_fk' => 'required|integer|exists:frontend_sites,id',
            'name' => $request->ajax() ? 'nullable|string|max:255' : 'required|string|max:255',
            'slug' => $request->ajax()
                ? 'nullable|string|max:255'
                : 'required|string|max:255|unique:frontend_pages,slug,' . $id . ',id,site_fk,' . $request->site_fk,
            'layout' => 'nullable|string',
            'entry_script' => ['nullable', 'string', function ($attribute, $value, $fail) {
                if ($value && preg_match('/\{!!\s*\$/', $value)) {
                    $fail('Entry Script cannot contain {!! $... !!} syntax. Use Page Content for component output. Entry Script is for @php logic only.');
                }
            }],
            'page_content' => 'nullable|string',
            'use_custom_layout' => 'nullable|boolean',
            'is_default' => 'nullable|boolean',
            'status' => 'nullable|boolean',
            'sort_order' => 'nullable|integer|min:0',
            'components' => 'nullable|array',
            'components.*' => 'integer|exists:frontend_components,id',
        ]);

        $data['is_default'] = $request->boolean('is_default');
        $data['status'] = $request->boolean('status');
        $data['use_custom_layout'] = $request->boolean('use_custom_layout');

        // Auto-unset other default pages in same site
        if ($data['is_default']) {
            FrontendPage::where('site_fk', $data['site_fk'])->where('id', '!=', $id)->where('is_default', true)->update(['is_default' => false]);
        }

        $page->update($request->ajax() ? Arr::except($data, ['name', 'slug']) : $data);

        app(BladeSyncService::class)->syncAll();

        $page->components()->detach();
        if ($request->has('components')) {
            $sort = 0;
            foreach ($request->components as $compId) {
                $page->components()->attach($compId, ['sort' => $sort++]);
            }
        }

        if ($request->ajax()) {
            return response()->json(['message' => 'Code updated successfully!']);
        }

        if (!$request->filled('entry_script') && !$request->filled('page_content') && !$request->has('components')) {
            flash()->warning('Page created but no Entry Script, Page Content, or Components were provided. The page may appear empty.');
        } else {
            flash()->success('Page updated successfully!');
        }
        return redirect()->route('frontend-site.pages.index', ['site_id' => $page->site_fk]);
    }

    public function destroy($id)
    {
        $page = FrontendPage::findOrFail($id);
        $siteId = $page->site_fk;
        $page->components()->detach();
        $page->delete();

        app(BladeSyncService::class)->syncAll();

        flash()->success('Page deleted successfully.');
        return redirect()->route('frontend-site.pages.index', ['site_id' => $siteId]);
    }

    public function toggleDefault($id)
    {
        $page = FrontendPage::findOrFail($id);

        FrontendPage::where('site_fk', $page->site_fk)->where('is_default', true)->update(['is_default' => false]);

        $page->update(['is_default' => true]);

        app(BladeSyncService::class)->syncAll();

        flash()->success("'{$page->name}' is now the default page");

        return response()->json(['is_default' => true, 'name' => $page->name]);
    }

    public function reorder(Request $request)
    {
        $ids = $request->input('ids', []);
        $page = (int) $request->input('page', 1);
        $perPage = 10;
        $offset = ($page - 1) * $perPage;
        foreach ($ids as $index => $id) {
            FrontendPage::where('id', $id)->update(['sort_order' => $offset + $index + 1]);
        }
        app(BladeSyncService::class)->syncAll();
        return response()->json(['success' => true]);
    }

    public function toggleStatus($id)
    {
        $page = FrontendPage::findOrFail($id);
        $page->update(['status' => !$page->status]);

        app(BladeSyncService::class)->syncAll();

        return response()->json(['status' => $page->fresh()->status]);
    }

    public function layoutBuilder()
    {
        return view('backend.module.frontendSite.layout-builder');
    }
}