Enhance homepage with dynamic success and portfolio settings: replace static content with values from SuccessSettings and PortfolioSettings, and implement loops for skill and portfolio items.

This commit is contained in:
2025-07-28 15:18:32 +05:00
parent fb4479929d
commit 6d564bb285
7 changed files with 321 additions and 57 deletions

View File

@@ -0,0 +1,106 @@
<?php
namespace App\Filament\Pages;
use App\Settings\PortfolioSettings;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Form;
use Filament\Pages\SettingsPage;
use Illuminate\Contracts\Support\Htmlable;
class ManagePortfolio extends SettingsPage
{
protected static ?string $navigationIcon = 'heroicon-o-briefcase';
protected static string $settings = PortfolioSettings::class;
public function form(Form $form): Form
{
return $form
->schema([
Section::make('Portfolio Section Content')
->description('Manage the main content for the portfolio section.')
->icon('heroicon-o-document-text')
->schema([
TextInput::make('portfolio_header')
->label('Header')
->required()
->maxLength(255),
Grid::make()->schema([
TextInput::make('portfolio_button_text')
->label('Button Text')
->maxLength(50),
TextInput::make('portfolio_button_url')
->label('Button URL')
->maxLength(255)
->url(),
])->columns(2),
]),
Section::make('Portfolio Items')
->description('Manage individual portfolio items.')
->icon('heroicon-o-photo')
->schema([
Repeater::make('portfolio_items')
->label('Portfolio Items')
->schema([
FileUpload::make('image')
->label('Image (700x525)')
->image() ->maxSize(2048)
->disk('public')
->directory('portfolio-images')
->required(),
TextInput::make('category')
->label('Category')
->required()
->maxLength(100),
TextInput::make('title')
->label('Title')
->required()
->maxLength(255),
TextInput::make('link')
->label('Link')
->required()
->maxLength(255)
->url(),
])
->columns(2)
->minItems(1)
->maxItems(8)
->defaultItems(4)
->reorderable()
->collapsible(),
]),
])
->columns(1)
->statePath('data');
}
public static function getNavigationGroup(): ?string
{
return __('CMS');
}
public static function getNavigationLabel(): string
{
return __('Portfolio');
}
public function getTitle(): string|Htmlable
{
return 'Portfolio';
}
public function getHeading(): string|Htmlable
{
return 'Edit portfolio section content from here';
}
public function getSubheading(): string|Htmlable|null
{
return 'Manage the portfolio section content, including items, categories, and titles.';
}
}

View File

@@ -0,0 +1,104 @@
<?php
namespace App\Filament\Pages;
use App\Settings\SuccessSettings;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Form;
use Filament\Pages\SettingsPage;
use Illuminate\Contracts\Support\Htmlable;
class ManageSuccess extends SettingsPage
{
protected static ?string $navigationIcon = 'heroicon-o-check-circle';
protected static string $settings = SuccessSettings::class;
public function form(Form $form): Form
{
return $form
->schema([
Section::make('Success Section Content')
->description('Manage the main content for the success section.')
->icon('heroicon-o-document-text')
->schema([
TextInput::make('success_subtitle')
->label('Subtitle')
->maxLength(100),
TextInput::make('success_header')
->label('Header')
->required()
->maxLength(255),
Textarea::make('success_paragraph')
->label('Paragraph')
->rows(3)
->maxLength(65535),
Grid::make()->schema([
TextInput::make('success_button_text')
->label('Button Text')
->maxLength(50),
TextInput::make('success_button_url')
->label('Button URL')
->maxLength(255)
->url(),
])->columns(2),
]),
Section::make('Skill Items')
->description('Manage the skill items with their names and percentages.')
->icon('heroicon-o-adjustments-vertical')
->schema([
Repeater::make('skill_items')
->label('Skill Items')
->schema([
TextInput::make('name')
->label('Skill Name')
->required()
->maxLength(100),
TextInput::make('percentage')
->label('Percentage')
->numeric()
->required()
->minValue(0)
->maxValue(100),
])
->columns(2)
->minItems(1)
->maxItems(5)
->defaultItems(2)
->reorderable()
->collapsible(),
]),
])
->columns(1)
->statePath('data');
}
public static function getNavigationGroup(): ?string
{
return __('CMS');
}
public static function getNavigationLabel(): string
{
return __('Success Section');
}
public function getTitle(): string|Htmlable
{
return 'Success Section';
}
public function getHeading(): string|Htmlable
{
return 'Edit success section content from here';
}
public function getSubheading(): string|Htmlable|null
{
return 'Manage the success section content, including text, button, and skill bars.';
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class PortfolioSettings extends Settings
{
public string $portfolio_header;
public string $portfolio_button_text;
public string $portfolio_button_url;
public array $portfolio_items;
public static function group(): string
{
return 'cms_portfolio';
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class SuccessSettings extends Settings
{
public string $success_subtitle;
public string $success_header;
public string $success_paragraph;
public string $success_button_text;
public string $success_button_url;
public array $skill_items;
public static function group(): string
{
return 'cms_success';
}
}

View File

@@ -0,0 +1,19 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
return new class extends SettingsMigration
{
public function up(): void
{
$this->migrator->add('cms_success.success_subtitle', 'Construction Advices');
$this->migrator->add('cms_success.success_header', 'Building Success With Expert Advisory Services');
$this->migrator->add('cms_success.success_paragraph', 'With a focus on innovation and sustainability, we help you navigate complex challenges, ensuring');
$this->migrator->add('cms_success.success_button_text', 'Get Advices');
$this->migrator->add('cms_success.success_button_url', 'contact.html');
$this->migrator->add('cms_success.skill_items', [
['name' => 'Building Construction', 'percentage' => 89],
['name' => 'Interiors Design', 'percentage' => 70],
]);
}
};

View File

@@ -0,0 +1,19 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
return new class extends SettingsMigration
{
public function up(): void
{
$this->migrator->add('cms_portfolio.portfolio_header', 'Get Expert Construction Advice and a Free Quote');
$this->migrator->add('cms_portfolio.portfolio_button_text', 'Start a Journey');
$this->migrator->add('cms_portfolio.portfolio_button_url', 'request-quote.html');
$this->migrator->add('cms_portfolio.portfolio_items', [
['image' => 'portfolio/portfolio-6.jpg', 'category' => 'Hospitality', 'title' => 'Seaside Resort Expansion', 'link' => '#'],
['image' => 'portfolio/portfolio-2.jpg', 'category' => 'Retail', 'title' => 'Urban Mall Development', 'link' => '#'],
['image' => 'portfolio/portfolio-4.jpg', 'category' => 'Residential', 'title' => 'Luxury Home Renovation', 'link' => '#'],
['image' => 'portfolio/portfolio-8.jpg', 'category' => 'Architecture', 'title' => 'Modern Architecture', 'link' => '#'],
]);
}
};

View File

@@ -1,6 +1,8 @@
@extends('web.layouts.app')
@inject('solutionSettings', 'App\Settings\SolutionSettings')
@inject('successSettings', 'App\Settings\SuccessSettings')
@inject('portfolioSettings', 'App\Settings\PortfolioSettings')
@section('content')
<!-- Banner Area Start -->
@@ -167,11 +169,11 @@
<div class="row al-center">
<div class="col-lg-6 lg-mb-25">
<div class="success__area-title mr-70 xl-mr-0">
<span class="subtitle wow fadeInLeft" data-wow-delay=".4s">Construction Advices</span>
<h2 class="title_split_anim mb-20">Building Success With Expert Advisory Services</h2>
<p class="wow fadeInUp" data-wow-delay=".4s">With a focus on innovation and sustainability, we help you navigate complex challenges, ensuring</p>
<span class="subtitle wow fadeInLeft" data-wow-delay=".4s">{{ $successSettings->success_subtitle }}</span>
<h2 class="title_split_anim mb-20">{{ $successSettings->success_header }}</h2>
<p class="wow fadeInUp" data-wow-delay=".4s">{{ $successSettings->success_paragraph }}</p>
<div class="item_bounce">
<a class="build_button mt-25" href="contact.html">Get Advices<i class="flaticon-right-up"></i></a>
<a class="build_button mt-25" href="{{ $successSettings->success_button_url }}">{{ $successSettings->success_button_text }}<i class="flaticon-right-up"></i></a>
</div>
</div>
</div>
@@ -179,24 +181,17 @@
<div class="success__area-right">
<img class="lg_img_full wow img_top_animation" src="/web/assets/img/page/skill.jpg" alt="image">
<div class="success__area-right-skill mt-40 wow fadeInUp" data-wow-delay=".5s">
<div class="skill__area-item">
<div class="skill__area-item-content">
<h6>Building Construction</h6>
<span class="skill__area-item-count"><span class="counter">89</span>%</span>
@foreach($successSettings->skill_items as $skill)
<div class="skill__area-item">
<div class="skill__area-item-content">
<h6>{{ $skill['name'] }}</h6>
<span class="skill__area-item-count"><span class="counter">{{ $skill['percentage'] }}</span>%</span>
</div>
<div class="skill__area-item-inner">
<div class="skill__area-item-bar" data-width="{{ $skill['percentage'] }}"></div>
</div>
</div>
<div class="skill__area-item-inner">
<div class="skill__area-item-bar" data-width="89"></div>
</div>
</div>
<div class="skill__area-item">
<div class="skill__area-item-content">
<h6>Interiors Design</h6>
<span class="skill__area-item-count"><span class="counter">70</span>%</span>
</div>
<div class="skill__area-item-inner">
<div class="skill__area-item-bar" data-width="70"></div>
</div>
</div>
@endforeach
</div>
</div>
</div>
@@ -210,42 +205,17 @@
<div class="row">
<div class="col-xl-12">
<div class="portfolio__four-area">
<div class="portfolio__four-area-item">
<img src="/web/assets/img/portfolio/portfolio-6.jpg" alt="image">
<div class="portfolio__four-area-item-area">
<div class="portfolio__one-item-content">
<span>Hospitality</span>
<h4><a href="#" class="text-white">Seaside Resort Expansion</a></h4>
@foreach($portfolioSettings->portfolio_items as $item)
<div class="portfolio__four-area-item">
<img src="/storage/{{ $item['image'] }}" alt="image">
<div class="portfolio__four-area-item-area">
<div class="portfolio__one-item-content">
<span>{{ $item['category'] }}</span>
<h4><a href="{{ $item['link'] }}" class="text-white">{{ $item['title'] }}</a></h4>
</div>
</div>
</div>
</div>
<div class="portfolio__four-area-item">
<img src="/web/assets/img/portfolio/portfolio-2.jpg" alt="image">
<div class="portfolio__four-area-item-area">
<div class="portfolio__one-item-content">
<span>Retail</span>
<h4><a href="#" class="text-white">Urban Mall Development</a></h4>
</div>
</div>
</div>
<div class="portfolio__four-area-item">
<img src="/web/assets/img/portfolio/portfolio-4.jpg" alt="image">
<div class="portfolio__four-area-item-area">
<div class="portfolio__one-item-content">
<span>Residential</span>
<h4><a href="#" class="text-white">Luxury Home Renovation</a></h4>
</div>
</div>
</div>
<div class="portfolio__four-area-item">
<img src="/web/assets/img/portfolio/portfolio-8.jpg" alt="image">
<div class="portfolio__four-area-item-area">
<div class="portfolio__one-item-content">
<span>Architecture</span>
<h4><a href="#" class="text-white">Modern Architecture</a></h4>
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
@@ -253,11 +223,11 @@
<div class="container mt-60">
<div class="row al-center">
<div class="col-xl-5 col-md-7 md-mb-25 lg-t-center title_split_anim">
<h3>Get Expert Construction Advice and a Free Quote</h3>
<h3>{{ $portfolioSettings->portfolio_header }}</h3>
</div>
<div class="col-xl-7 col-md-5 t-right lg-t-center">
<div class="item_bounce">
<a class="build_button" href="request-quote.html">Start a Journey<i class="flaticon-right-up"></i></a>
<a class="build_button" href="{{ $portfolioSettings->portfolio_button_url }}">{{ $portfolioSettings->portfolio_button_text }}<i class="flaticon-right-up"></i></a>
</div>
</div>
</div>