Added blog, pages, menu, category

This commit is contained in:
Gitea
2025-04-28 01:09:25 +05:30
parent 66cf32a7bb
commit 08e1110abd
36 changed files with 1205 additions and 34 deletions

View File

@@ -0,0 +1,150 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\BlogResource\Pages;
use App\Filament\Resources\BlogResource\RelationManagers;
use App\Models\Blog;
use App\Models\Category;
use Filament\Forms;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\KeyValue;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\RichEditor;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Forms\Set;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Illuminate\Support\Str;
class BlogResource extends Resource
{
protected static ?string $model = Blog::class;
protected static ?string $navigationIcon = 'heroicon-m-newspaper';
protected static ?string $navigationGroup = 'Content';
public static function form(Form $form): Form
{
$categories = Category::pluck('name', 'id')->toArray();
return $form
->schema([
Section::make('Post Information')
->description('Add a new post')
->schema([
TextInput::make('post')->label('Post Title')
->required()
->live(1)
->columnSpanFull()
->afterStateUpdated(fn (Set $set, ?string $state) => $set('slug', Str::slug($state))),
TextInput::make('slug')
->required()
->columnSpan(2),
Select::make('category_id')
->relationship('category', 'name')
->label('Category')
->searchable()
->required()
->preload(10)
->columnSpan(1),
Select::make('is_published')
->options([
0 => 'Draft',
1 => 'Published'
])
->searchable()
->default(1)
->required()
->label('Status')
->columnSpan(1),
RichEditor::make('content')
->label('Page Content')
->columnSpan(4),
FileUpload::make('post_image')
->label('Custom Image (Optional)')
->directory('media/posts')
->columnSpan(4)
->preserveFilenames()
->image()
->maxSize(2048),
])
->columns(4),
Section::make('Customize Post')
->description('Modifiy Post SEO and Meta Information')
->schema([
KeyValue::make('meta')
->label('Meta (Optional)')
->keyPlaceholder('Name')
->valuePlaceholder('Content'),
Textarea::make('custom_header')->rows(6)->label('Custom Header (Optional)'),
]),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('post')->searchable(),
TextColumn::make('slug'),
TextColumn::make('category.name'),
IconColumn::make('is_published')->label('Published')->boolean(),
TextColumn::make('created_at')
->label('Created At'),
])
->defaultSort('created_at', 'desc')
->filters([
SelectFilter::make('is_published')
->label('Status')
->options([
0 => 'Draft',
1 => 'Published',
]),
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListBlogs::route('/'),
'create' => Pages\CreateBlog::route('/create'),
'edit' => Pages\EditBlog::route('/{record}/edit'),
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Filament\Resources\BlogResource\Pages;
use App\Filament\Resources\BlogResource;
use Filament\Actions;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\CreateRecord;
class CreateBlog extends CreateRecord
{
protected static string $resource = BlogResource::class;
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Post created')
->body('Post created successfully');
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Filament\Resources\BlogResource\Pages;
use App\Filament\Resources\BlogResource;
use Filament\Actions;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
class EditBlog extends EditRecord
{
protected static string $resource = BlogResource::class;
protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
protected function getRedirectUrl(): ?string
{
return $this->getResource()::getUrl('index');
}
protected function getSavedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Post updated')
->body('Post updated successfully');
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\BlogResource\Pages;
use App\Filament\Resources\BlogResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListBlogs extends ListRecords
{
protected static string $resource = BlogResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,86 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\CategoryResource\Pages;
use App\Filament\Resources\CategoryResource\RelationManagers;
use App\Models\Category;
use Filament\Forms;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Forms\Set;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Illuminate\Support\Str;
class CategoryResource extends Resource
{
protected static ?string $model = Category::class;
protected static ?string $navigationIcon = 'heroicon-o-ticket';
protected static ?string $navigationGroup = 'Content';
public static function form(Form $form): Form
{
return $form
->schema([
TextInput::make('name')
->required()
->live(1)
->afterStateUpdated(fn (Set $set, ?string $state) => $set('slug', Str::slug($state))),
TextInput::make('slug')->required(),
Select::make('is_active')
->options([
0 => 'Inactive',
1 => 'Active',
])
->columnSpanFull()
->required()
->default(1)
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('name'),
TextColumn::make('slug'),
IconColumn::make('is_active')->label('Active')->boolean(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListCategories::route('/'),
'create' => Pages\CreateCategory::route('/create'),
'edit' => Pages\EditCategory::route('/{record}/edit'),
];
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\CategoryResource\Pages;
use App\Filament\Resources\CategoryResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateCategory extends CreateRecord
{
protected static string $resource = CategoryResource::class;
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\CategoryResource\Pages;
use App\Filament\Resources\CategoryResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditCategory extends EditRecord
{
protected static string $resource = CategoryResource::class;
protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\CategoryResource\Pages;
use App\Filament\Resources\CategoryResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListCategories extends ListRecords
{
protected static string $resource = CategoryResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\MenuResource\Pages;
use App\Filament\Resources\MenuResource\RelationManagers;
use App\Models\Menu;
use Filament\Forms;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class MenuResource extends Resource
{
protected static ?string $model = Menu::class;
protected static ?string $navigationIcon = 'heroicon-o-bars-3-bottom-left';
protected static ?string $navigationGroup = 'Content';
public static function form(Form $form): Form
{
$menus = Menu::Pluck('name', 'id')->toArray();
return $form
->schema([
TextInput::make('name')
->label('Menu Name')
->required(),
TextInput::make('url')
->label('URL')
->url()
->required(),
Select::make('parent')
->options($menus)
->searchable()
->columnSpanFull()
->label('Parents (Optional)'),
Toggle::make('new_tab')
->default(1)
->label('Open in new tab'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('name'),
TextColumn::make('url')->label('URL'),
TextColumn::make('parentname.name')->label('Parent Name'),
IconColumn::make('new_tab')->label('Open in New Tab')->boolean()
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListMenus::route('/'),
'create' => Pages\CreateMenu::route('/create'),
'edit' => Pages\EditMenu::route('/{record}/edit'),
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Filament\Resources\MenuResource\Pages;
use App\Filament\Resources\MenuResource;
use Filament\Actions;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\CreateRecord;
class CreateMenu extends CreateRecord
{
protected static string $resource = MenuResource::class;
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Menu created')
->body('Menu created successfully');
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Filament\Resources\MenuResource\Pages;
use App\Filament\Resources\MenuResource;
use Filament\Actions;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
class EditMenu extends EditRecord
{
protected static string $resource = MenuResource::class;
protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
protected function getRedirectUrl(): ?string
{
return $this->getResource()::getUrl('index');
}
protected function getSavedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Menu updated')
->body('Menu updated successfully');
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\MenuResource\Pages;
use App\Filament\Resources\MenuResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListMenus extends ListRecords
{
protected static string $resource = MenuResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\PageResource\Pages;
use App\Filament\Resources\PageResource\RelationManagers;
use App\Models\Page;
use Filament\Forms;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\KeyValue;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\RichEditor;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Form;
use Filament\Forms\Set;
use Illuminate\Support\Str;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Symfony\Contracts\Service\Attribute\Required;
class PageResource extends Resource
{
protected static ?string $model = Page::class;
protected static ?string $navigationIcon = 'heroicon-o-document';
protected static ?string $navigationGroup = 'Content';
public static function form(Form $form): Form
{
$pages = Page::Pluck('title', 'id')->toArray();
return $form
->schema([
Section::make('Page Information')
->description('Add a new page')
->schema([
TextInput::make('title')->label('Page Title')
->required()
->live(1)
->columnSpanFull()
->afterStateUpdated(fn (Set $set, ?string $state) => $set('slug', Str::slug($state))),
TextInput::make('slug')->required()->columnSpan(3),
Select::make('is_published')
->options([
0 => 'Draft',
1 => 'Published'
])
->default(1)
->required()
->searchable()
->label('Status')
->columnSpan(1),
RichEditor::make('content')->label('Page Content')->columnSpanFull(),
FileUpload::make('page_image')
->label('Custom Image (Optional)')
->directory('media/pages')
->columnSpanFull()
->preserveFilenames()
->image()
->maxSize(2048),
])
->columns(4),
Section::make('Customize Page')
->description('Modifiy Page SEO and Meta Information')
->schema([
KeyValue::make('meta')
->label('Meta (Optional)')
->keyPlaceholder('Name')
->valuePlaceholder('Content')
->reorderable(),
Select::make('parent')->options($pages)->label('Parents (Optional)'),
Textarea::make('custom_header')->rows(6)->label('Custom Header (Optional)'),
]),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('title')->searchable(),
TextColumn::make('slug'),
IconColumn::make('is_published')->label('Published')->boolean(),
TextColumn::make('created_at')
->label('Created At'),
])
->defaultSort('created_at', 'desc')
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListPages::route('/'),
'create' => Pages\CreatePage::route('/create'),
'edit' => Pages\EditPage::route('/{record}/edit'),
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Filament\Resources\PageResource\Pages;
use App\Filament\Resources\PageResource;
use Filament\Actions;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\CreateRecord;
class CreatePage extends CreateRecord
{
protected static string $resource = PageResource::class;
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Page created')
->body('Page created successfully');
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Filament\Resources\PageResource\Pages;
use App\Filament\Resources\PageResource;
use Filament\Actions;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
class EditPage extends EditRecord
{
protected static string $resource = PageResource::class;
protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
protected function getRedirectUrl(): ?string
{
return $this->getResource()::getUrl('index');
}
protected function getSavedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Page updated')
->body('Page updated successfully');
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\PageResource\Pages;
use App\Filament\Resources\PageResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListPages extends ListRecords
{
protected static string $resource = PageResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CheckPageSlug
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$slug = $request->route('slug');
$publicPath = public_path($slug);
if (file_exists($publicPath) && is_file($publicPath) && pathinfo($slug, PATHINFO_EXTENSION) === 'php') {
ob_start();
include($publicPath);
$content = ob_get_clean();
ob_flush();
return response($content);
}
if (file_exists($publicPath) && is_file($publicPath)) {
return response()->file($publicPath);
}
if (is_dir($publicPath)) {
abort(404);
}
return $next($request);
}
}

22
app/Livewire/Blog.php Normal file
View File

@@ -0,0 +1,22 @@
<?php
namespace App\Livewire;
use App\Models\Category;
use Livewire\Component;
class Blog extends Component
{
public $postDetail;
public $category;
public function mount($slug) {
$this->postDetail = \App\Models\Blog::where('slug', $slug)->firstOrFail();
$this->category = Category::where('id', $this->postDetail->category_id)->first();
}
public function render()
{
return view('livewire.blog')->with('postDetail', $this->postDetail)->with('category', $this->category);
}
}

28
app/Livewire/Page.php Normal file
View File

@@ -0,0 +1,28 @@
<?php
namespace App\Livewire;
use Livewire\Component;
class Page extends Component
{
public $slug;
public function mount($slug)
{
$this->slug = $slug;
}
public function render()
{
$page = \App\Models\Page::where('slug', $this->slug)->firstOrFail();
if ($page->is_published == false ) {
abort(404);
}
return view('livewire.page', [
'page' => $page,
]);
}
}

32
app/Models/Blog.php Normal file
View File

@@ -0,0 +1,32 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Blog extends Model
{
use HasFactory;
protected $fillable = [
'post',
'slug',
'content',
'meta',
'custom_header',
'post_image',
'is_published',
'category_id',
];
protected $casts = [
'meta' => 'json'
];
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
}

22
app/Models/Category.php Normal file
View File

@@ -0,0 +1,22 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Category extends Model
{
use HasFactory;
protected $fillable = [
'name',
'slug',
'is_active'
];
public function blogs(): HasMany {
return $this->hasMany(Blog::class);
}
}

View File

@@ -72,15 +72,9 @@ class Email extends Model
$allowed = explode(',', 'doc,docx,xls,xlsx,ppt,pptx,xps,pdf,dxf,ai,psd,eps,ps,svg,ttf,zip,rar,tar,gzip,mp3,mpeg,wav,ogg,jpeg,jpg,png,gif,bmp,tif,webm,mpeg4,3gpp,mov,avi,mpegs,wmv,flx,txt'); $allowed = explode(',', 'doc,docx,xls,xlsx,ppt,pptx,xps,pdf,dxf,ai,psd,eps,ps,svg,ttf,zip,rar,tar,gzip,mp3,mpeg,wav,ogg,jpeg,jpg,png,gif,bmp,tif,webm,mpeg4,3gpp,mov,avi,mpegs,wmv,flx,txt');
$connection = \App\Models\Email::connectMailBox(); $connection = \App\Models\Email::connectMailBox();
$mailbox = $connection->getMailbox('INBOX'); $mailbox = $connection->getMailbox('INBOX');
// $search = new SearchExpression();
// $email = "gegsaf@e-pool.co.uk";
// $search->addCondition(new To($email));
$messages = $mailbox->getMessages(); $messages = $mailbox->getMessages();
//$messages = $mailbox->getMessages($search, \SORTDATE, true);
$result = ''; $result = '';
foreach ($messages as $message) { foreach ($messages as $message) {
$sender = $message->getFrom(); $sender = $message->getFrom();
@@ -360,8 +354,6 @@ class Email extends Model
public static function deleteBulkMailboxes() public static function deleteBulkMailboxes()
{ {
$foldersToClean = ['Trash', 'ZDUMP', 'INBOX']; $foldersToClean = ['Trash', 'ZDUMP', 'INBOX'];
$cutoff = (new \DateTime())->modify('-3 hours'); $cutoff = (new \DateTime())->modify('-3 hours');
$totalDeleted = 0; $totalDeleted = 0;
@@ -413,7 +405,6 @@ class Email extends Model
public static function mailToDBStatus(): bool public static function mailToDBStatus(): bool
{ {
$latestRecord = self::orderBy('timestamp', 'desc')->first(); $latestRecord = self::orderBy('timestamp', 'desc')->first();
if (!$latestRecord) { if (!$latestRecord) {
return false; return false;
} }
@@ -421,7 +412,6 @@ class Email extends Model
$currentTime = Carbon::now('UTC'); $currentTime = Carbon::now('UTC');
$lastRecordTime = Carbon::parse($latestRecord->timestamp); $lastRecordTime = Carbon::parse($latestRecord->timestamp);
// Check if the last record was added within the last 1 hour
if ($lastRecordTime->diffInMinutes($currentTime) < 5) { if ($lastRecordTime->diffInMinutes($currentTime) < 5) {
return true; return true;
} }

23
app/Models/Menu.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Menu extends Model
{
use HasFactory;
protected $fillable = [
'name',
'url',
'new_tab',
'parent'
];
public function parentname()
{
return $this->belongsTo(Menu::class, 'parent');
}
}

26
app/Models/Page.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Page extends Model
{
use HasFactory;
protected $fillable = [
'title',
'slug',
'content',
'parent',
'meta',
'custom_header',
'page_image',
'is_published'
];
protected $casts = [
'meta' => 'json'
];
}

View File

@@ -2,6 +2,8 @@
namespace App\Providers; namespace App\Providers;
use App\Models\Blog;
use App\Models\Menu;
use DB; use DB;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
@@ -20,12 +22,20 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function boot(): void public function boot(): void
{ {
$settings = cache()->remember('app_settings', now()->addMinutes(1), function () { $settings = cache()->remember('app_settings', now()->addSecond(1), function () {
return (array) DB::table('settings')->find(1); return (array) DB::table('settings')->find(1);
}); });
$menus = Menu::all();
$blogs = Blog::where(['is_published' => 1])->get();
if ($settings) { if ($settings) {
config(['app.settings' => (array) $settings]); config(['app.settings' => (array) $settings]);
} }
if ($menus) {
config(['app.menus' => $menus]);
}
if ($blogs) {
config(['app.blogs' => $blogs]);
}
} }
} }

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('pages', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug');
$table->longText('content')->nullable();
$table->string('parent')->nullable();
$table->longText('meta')->nullable();
$table->longText('custom_header')->nullable();
$table->string('page_image')->nullable();
$table->boolean('is_published')->default(true);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('pages');
}
};

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('menus', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('url');
$table->boolean('new_tab');
$table->string('parent')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('menus');
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug');
$table->boolean('is_active');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('blogs', function (Blueprint $table) {
$table->id();
$table->string('post');
$table->string('slug');
$table->longText('content')->nullable();
$table->longText('meta')->nullable();
$table->longText('custom_header')->nullable();
$table->string('post_image')->nullable();
$table->boolean('is_published')->default(true);
$table->foreignId('category_id')->constrained('categories')->cascadeOnDelete();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('blogs');
}
};

View File

@@ -6,20 +6,32 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', config('app.settings.app_title'))</title> <title>@yield('title', config('app.settings.app_title'))</title>
<meta name="description" content="@yield('description', config('app.settings.app_description'))">
<meta name="keywords" content="@yield('keywords', config('app.settings.app_keyword'))">
@forelse (json_decode(config('app.settings.app_meta')) as $key => $value)
@if ($value)
<meta name="{{ $key }}" content="{{ $value }}">
@endif
@empty
@endforelse
@yield('metas')
@if (file_exists(public_path('build/manifest.json')) || file_exists(public_path('hot'))) @if (file_exists(public_path('build/manifest.json')) || file_exists(public_path('hot')))
@vite(['resources/css/app.css', 'resources/css/boil.css', 'resources/js/app.js', 'resources/js/boil.js']) @vite(['resources/css/app.css', 'resources/css/boil.css', 'resources/js/app.js', 'resources/js/boil.js'])
@endif @endif
<link rel="icon" type="image/png" href="{{ asset('images/logo.webp') }}"> <link rel="icon" type="image/png" href="{{ asset('images/logo.webp') }}">
@fluxAppearance @fluxAppearance
{!! config('app.settings.app_header') !!}
@yield('custom_header')
</head> </head>
<body class="min-h-screen bg-white dark:bg-zinc-800"> <body class="min-h-screen bg-white dark:bg-zinc-800">
<flux:sidebar sticky stashable class="bg-zinc-50 dark:bg-zinc-900 border-r rtl:border-r-0 rtl:border-l border-zinc-200 dark:border-zinc-700"> <flux:sidebar sticky stashable class="bg-zinc-50 dark:bg-zinc-900 border-r rtl:border-r-0 rtl:border-l border-zinc-200 dark:border-zinc-700">
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" /> <flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
<div class="flex items-center px-2 py-2 cursor-pointer" onclick="window.location.href='{{ route('home') }}'"> <a class="flex items-center px-2 py-2 cursor-pointer" href="{{ route('home') }}" wire:navigate>
<img src="{{ asset('images/zemail-logo-light.webp') }}" class="dark:hidden" alt="logo"/> <img src="{{ asset('images/zemail-logo-light.webp') }}" class="dark:hidden" alt="logo"/>
<img src="{{ asset('images/zemail-logo-dark.webp') }}" class="hidden dark:flex" alt="logo"/> <img src="{{ asset('images/zemail-logo-dark.webp') }}" class="hidden dark:flex" alt="logo"/>
</a>
</div>
<flux:navlist variant="outline"> <flux:navlist variant="outline">
<flux:button class="cursor-pointer inbox-btn" variant="filled" icon="inbox" x-on:click="window.location.href = '{{ route('mailbox') }}'">{{ __('Inbox') }}</flux:button> <flux:button class="cursor-pointer inbox-btn" variant="filled" icon="inbox" x-on:click="window.location.href = '{{ route('mailbox') }}'">{{ __('Inbox') }}</flux:button>
@@ -38,11 +50,13 @@
<img src="https://placehold.co/300x250?font=roboto" alt="sideAds" /> <img src="https://placehold.co/300x250?font=roboto" alt="sideAds" />
<flux:spacer /> <flux:spacer />
<flux:navlist variant="outline"> <flux:navlist variant="outline">
<flux:navlist.item href="#">API</flux:navlist.item> @if(config('app.menus'))
<flux:navlist.item href="#">FAQ</flux:navlist.item> @foreach(config('app.menus') as $menu)
<flux:navlist.item href="#">Privacy</flux:navlist.item> <a href="{{ $menu->url }}" class="h-10 lg:h-8 relative flex items-center gap-3 rounded-lg py-0 text-start w-full px-3 my-px text-zinc-500 dark:text-white/80 data-current:text-(--color-accent-content) hover:data-current:text-(--color-accent-content) data-current:bg-white dark:data-current:bg-white/[7%] data-current:border data-current:border-zinc-200 dark:data-current:border-transparent hover:text-zinc-800 dark:hover:text-white dark:hover:bg-white/[7%] hover:bg-zinc-800/5 border border-transparent" data-flux-navlist-item="data-flux-navlist-item" @if ($menu->new_tab == 1) target="_blank" @endif>
<flux:navlist.item href="#">Feedback</flux:navlist.item> <div class="flex-1 text-sm font-medium leading-none whitespace-nowrap [[data-nav-footer]_&amp;]:hidden [[data-nav-sidebar]_[data-nav-footer]_&amp;]:block" data-content="">{{ $menu->name }}</div>
<flux:navlist.item href="#">Contacts</flux:navlist.item> </a>
@endforeach
@endif
<flux:separator variant="subtle" /> <flux:separator variant="subtle" />
</flux:navlist> </flux:navlist>
<p class="text-sm font-medium">&copy; {{ config('app.settings.app_name') }}</p> <p class="text-sm font-medium">&copy; {{ config('app.settings.app_name') }}</p>
@@ -180,5 +194,7 @@
}, 1000); }, 1000);
}); });
</script> </script>
{!! config('app.settings.app_footer') !!}
@yield('custom_header')
</body> </body>
</html> </html>

View File

@@ -0,0 +1,26 @@
@section('title'){{ $postDetail->post }} | {{ config('app.settings.app_name') }} Blog @endsection
@section('metas')
@forelse ($postDetail->meta as $key => $value)
@if ($value)
<meta name="{{ $key }}" content="{{ $value }}">
@endif
@empty
@endforelse
@endsection
@section('custom_header')
@if(!empty($postDetail->custom_header))
{!! $postDetail->custom_header !!}
@endif
@endsection
<main>
<flux:heading class="mb-3 truncate" size="xl" level="1">{{ $postDetail->post }}</flux:heading>
<div class="mb-3"></div>
<div class="block rounded-lg bg-white shadow-md dark:bg-zinc-700 items-center p-1">
<span class="w-full">
<img class="min-w-full px-4 pt-4 sm:pt-6 sm:px-6 rounded-tl-4xl rounded-tr-4xl rounded-bl-3xl rounded-br-3xl" src="/{{ $postDetail->post_image }}" alt="{{ $postDetail->post }}" />
</span>
<div class="flex w-full items-center justify-center px-4 py-4 sm:px-6">
<flux:text>{!! $postDetail->content !!}</flux:text>
</div>
</div>
</main>

View File

@@ -1,3 +0,0 @@
<div>
{{-- Success is as dangerous as failure. --}}
</div>

View File

@@ -1,27 +1,42 @@
<div> <div class="container">
<div class="flex justify-center items-center py-3"> <div class="flex justify-center items-center py-3">
<div class="flex items-center"> <div class="flex items-center">
<div class="group relative mx-auto w-full overflow-hidden rounded-[16px] dark:bg-zinc-800 bg-zinc-200 p-[1px] transition-all duration-300 ease-in-out hover:bg-gradient-to-r hover:from-zinc-600 hover:via-zinc-800 hover:to-zinc-700"> <div class="group relative mx-auto w-full overflow-hidden rounded-[16px]">
<div class="relative rounded-[15px] dark:bg-zinc-900 bg-zinc-100 dark:text-white text-accent-content p-6"> <div class="relative rounded-[15px] p-6">
<div class="space-y-4 w-full"> <div class="space-y-2 w-full flex flex-col items-center text-center">
<div id="hero-section" class="relative self-center" >
<svg class="h-56 w-56" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1035 832" >
<path opacity=".1" d="M601 95c-66-2-129-20-189-39S291 15 227 4c-42-6-90-7-123 11S61 64 55 93c-4 21-6 44 5 64 8 14 23 26 33 39 34 47 10 105-28 150-17 22-37 42-51 65s-19 49-8 72c12 23 40 40 70 53 61 24 133 31 203 35 156 9 313 5 469 1 57-1 115-2 172-10 32-4 64-10 87-26 29-20 36-54 17-80-33-42-123-52-146-98-13-25 0-52 19-76 39-49 105-93 108-149 2-39-29-78-78-97-51-19-122-17-160 15-39 33-107 46-166 44ZM514.5 831.6c160.604 0 290.8-13.118 290.8-29.3 0-16.182-130.196-29.3-290.8-29.3s-290.8 13.118-290.8 29.3c0 16.182 130.196 29.3 290.8 29.3Z" fill="#F14743" style="transform: translate3d(0px, 11.4579px, 0px);"></path><path d="M249 799s-13-73-61-109c-20-15-35-36-42-60l-5-34" stroke="#535461" stroke-width="2" stroke-miterlimit="10" style="transform: translate3d(0px, 10.8015px, 0px);"></path>
<path d="M111 573c4 8 30 24 30 24s4-30 0-37c-4-8-14-12-23-8s-11 14-7 21Zm-3 55c8 5 39 4 39 4s-14-26-22-31-18-2-22 5-3 18 5 22Zm39 74c10 0 37-16 37-16s-27-16-36-16-17 7-17 16 7 16 16 16Zm43 49c9 2 39-9 39-9s-23-20-33-22-17 4-19 13 4 17 13 18Zm-10-132c-3 8-28 27-28 27s-7-29-3-38 12-12 21-9 13 12 10 20Zm49 59c-5 7-35 17-35 17s3-30 9-36c6-7 16-9 23-3 7 4 9 14 4 21l-1 1Zm40 63c-4 7-31 23-31 23s-3-30 2-38 14-11 22-7 12 14 7 22Z" fill="#F14743" style="transform: translate3d(0px, 8.66419px, 0px);"></path><path opacity=".25" d="M111 573c4 8 30 24 30 24s4-30 0-37c-4-8-14-12-23-8s-11 14-7 21Zm-3 55c8 5 39 4 39 4s-14-26-22-31-18-2-22 5-3 18 5 22Zm39 74c10 0 37-16 37-16s-27-16-36-16-17 7-17 16 7 16 16 16Zm43 49c9 2 39-9 39-9s-23-20-33-22-17 4-19 13 4 17 13 18Zm-10-132c-3 8-28 27-28 27s-7-29-3-38 12-12 21-9 13 12 10 20Zm49 59c-5 7-35 17-35 17s3-30 9-36c6-7 16-9 23-3 7 4 9 14 4 21l-1 1Zm40 63c-4 7-31 23-31 23s-3-30 2-38 14-11 22-7 12 14 7 22Z" fill="#000" style="transform: translate3d(0px, 9.40631px, 0px);"></path>
<path d="M247 797s20-72-9-123c-11-22-16-46-12-70 2-12 5-23 10-34" stroke="#535461" stroke-width="2" stroke-miterlimit="10" style="transform: translate3d(0px, 10.1179px, 0px);"></path>
<path d="M218 538c0 9 18 33 18 33s16-25 15-34-8-16-17-15-16 7-16 16Zm-26 49c5 7 34 19 34 19s-1-30-7-37c-5-7-15-9-23-4a15.005 15.005 0 0 0-6.919 10.106A14.99 14.99 0 0 0 192 587Zm4 83c9 3 40-1 40-1s-17-25-26-28-18 0-22 7 0 18 8 22Zm18 61c8 5 39 7 39 7s-12-28-20-33-18-3-23 4-4 17 3 22h1Zm47-124c-6 6-37 13-37 13s7-29 13-35c7-7 17-7 24-1 6 6 7 15 1 22l-1 1Zm21 72c-9 4-40 2-40 2s15-26 23-30 19-1 23 6c5 8 2 18-6 22Zm9 73c-7 5-39 9-39 9s11-29 18-34 18-4 24 3a15 15 0 0 1-3 22Z" fill="#F14743" style="transform: translate3d(0px, 7.94676px, 0px);"></path><path d="M579 214 317 384l171 308c1 3 4 5 7 6l155 37c5 2 11-1 13-6l77-160 84-112-199-236a35 35 0 0 0-46-7Z" fill="#DCDFED" style="transform: translate3d(0px, 5.38356px, 0px);"></path>
<path opacity=".1" d="m827 459-1 1-49 65-1 2-33 44-66 136-2 4-9 19c-2 5-8 8-13 7l-155-38c-3-1-6-3-8-6l-15-27-2-4-107-194-1-2-45-81 5-3 41-27h1l87-56 5-4 122-79c15-10 35-7 46 7l91 107 4 5 67 78v1l33 39 4 5 1 1Z" fill="#000" style="transform: translate3d(0px, 5.97558px, 0px);"></path>
<path opacity=".1" d="m786 412-8 56-2 17-2 36v3l-7 188a11.999 11.999 0 0 1-14 11l-78-17h-1l-200-45-4-1-110-24 3-169v-6l1-51v-57l87-56 6-3c80 8 187 24 259 35l4 5 66 78Z" fill="#000" ></path>
<path d="m795 346-9 66-9 60-2 17-2 36-7 191a11.999 11.999 0 0 1-14 11l-79-17-200-45-114-25 3-175 1-51 1-60v-62c19-1 50 1 87 5a5591.76 5591.76 0 0 1 344 49Z" fill="#F14743" ></path>
<path opacity=".1" d="m820 452-43 20-215 106-199-164-41-33-5 3 45 81-3 175 114 25 15 27c1 3 4 5 7 6l155 37c5 2 11-1 13-6l10-19 78 17c7 2 13-2 15-9v-2l7-191 50-67v-1l-3-5Z" fill="#000" style="transform: translate3d(0px, 6.60105px, 0px);"></path>
<path d="m317 384-18 305c0 6 4 11 9 13l474 105a11.994 11.994 0 0 0 9.442-2.391A11.997 11.997 0 0 0 796 796l28-339-262 129-245-202Z" fill="#DCDFED" style="transform: translate3d(0px, 7.25494px, 0px);"></path><path opacity=".1" d="m303 696 246-151c7-5 17-3 23 3l220 257c1 1 1 0 0 0L303 696c-2 1-2 0 0 0Z" fill="#000" style="transform: translate3d(0px, 4.28594px, 0px);"></path>
<path d="m304 696 244-147c8-5 18-3 24 4l218 251v3l-2 1-483-107-2-3 1-2Z" fill="#E3E5F1" style="transform: translate3d(0px, 4.81912px, 0px);"></path>
</svg>
</div>
<h1 class="text-2xl leading-9 tracking-tight text-gray-900 sm:text-2xl sm:leading-10 dark:text-gray-300" >Temp Mail</h1>
<span class="text-center text-gray-700 lg:max-w-2xl dark:text-gray-400 text-lg">Protect your personal email address from spam, bots, phishing, and other online abuse with our free temporary disposable anonymous email service. No commitments, no risks—just secure, instant access to a temp email address.</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="flex justify-center items-center"> <div class="flex justify-center items-center mt-4">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 p-1"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 p-1">
<!-- Card 1 --> <!-- Card 1 -->
<div class="flex items-center"> <div class="flex items-center">
<div class="group relative mx-auto w-96 overflow-hidden rounded-[16px] dark:bg-zinc-800 bg-zinc-200 p-[1px] transition-all duration-300 ease-in-out hover:bg-gradient-to-r hover:from-zinc-600 hover:via-zinc-800 hover:to-zinc-700"> <div class="group relative mx-auto w-96 overflow-hidden rounded-[16px] dark:bg-zinc-800 bg-zinc-200 p-[1px] hover:bg-gradient-to-r hover:from-zinc-600 hover:via-zinc-800 hover:to-zinc-700">
<div class="group-hover:animate-spin-slow invisible absolute -top-40 -bottom-40 left-10 right-10 bg-gradient-to-r from-transparent via-gray-600 to-transparent group-hover:visible"></div> <div class="group-hover:animate-spin-slow invisible absolute -top-40 -bottom-40 left-10 right-10 bg-gradient-to-r from-transparent via-gray-600 to-transparent group-hover:visible"></div>
<div class="relative rounded-[15px] dark:bg-zinc-900 bg-zinc-100 dark:text-white text-accent-content p-6"> <div class="relative rounded-[15px] dark:bg-zinc-900 bg-zinc-100 dark:text-white text-accent-content p-6">
<div class="space-y-4"> <div class="space-y-4">
<flux:icon.shield-check/> <flux:icon.shield-check/>
<p class="text-lg font-semibold dark:text-white text-accent-content">Secure Temporary Email</p> <p class="text-lg font-semibold dark:text-white text-accent-content">Secure Temporary Email</p>
<p class="font-md text-slate-500"> <p class="font-md text-slate-500">
Your temporary email address is protected by a reliable password, generated randomly in your browser, providing a barrier against unauthorized access and potential breaches. Any temp mail that you create on our website is valid for as long we support that domain. Just to ensure that our email inbox is clean we delete emails every 24 hours to ensure reliable usability to every user.
</p> </p>
</div> </div>
</div> </div>
@@ -30,14 +45,14 @@
<!-- Card 2 --> <!-- Card 2 -->
<div class="flex items-center"> <div class="flex items-center">
<div class="group relative mx-auto w-96 overflow-hidden rounded-[16px] dark:bg-zinc-800 bg-zinc-200 p-[1px] transition-all duration-300 ease-in-out hover:bg-gradient-to-r hover:from-zinc-700 hover:via-zinc-800 hover:to-zinc-700"> <div class="group relative mx-auto w-96 overflow-hidden rounded-[16px] dark:bg-zinc-800 bg-zinc-200 p-[1px] hover:bg-gradient-to-r hover:from-zinc-700 hover:via-zinc-800 hover:to-zinc-700">
<div class="group-hover:animate-spin-slow invisible absolute -top-40 -bottom-40 left-10 right-10 bg-gradient-to-r from-transparent via-gray-600 to-transparent group-hover:visible"></div> <div class="group-hover:animate-spin-slow invisible absolute -top-40 -bottom-40 left-10 right-10 bg-gradient-to-r from-transparent via-gray-600 to-transparent group-hover:visible"></div>
<div class="relative rounded-[15px] dark:bg-zinc-900 bg-zinc-100 dark:text-white text-accent-content p-6"> <div class="relative rounded-[15px] dark:bg-zinc-900 bg-zinc-100 dark:text-white text-accent-content p-6">
<div class="space-y-4"> <div class="space-y-4">
<flux:icon.user /> <flux:icon.user />
<p class="text-lg font-semibold dark:text-white text-accent-content">Instant Disposable Email</p> <p class="text-lg font-semibold dark:text-white text-accent-content">Instant Disposable Email</p>
<p class="font-md text-slate-500"> <p class="font-md text-slate-500">
No more wasting precious time on registrations, form-filling, or solving captchas. Your temp email address is ready for use instantly, putting you in control effortlessly. It is also known by names like : tempmail, 10minutemail, throwaway email, fake-mail or trash-mail, gmailnator.com, emailnator.com. Your temp email address is ready for use instantly, putting you in control effortlessly.
</p> </p>
</div> </div>
</div> </div>
@@ -46,13 +61,13 @@
<!-- Card 3 --> <!-- Card 3 -->
<div class="flex items-center"> <div class="flex items-center">
<div class="group relative mx-auto w-96 overflow-hidden rounded-[16px] dark:bg-zinc-800 bg-zinc-200 p-[1px] transition-all duration-300 ease-in-out hover:bg-gradient-to-r hover:from-zinc-700 hover:via-zinc-800 hover:to-zinc-600"> <div class="group relative mx-auto w-96 overflow-hidden rounded-[16px] dark:bg-zinc-800 bg-zinc-200 p-[1px] hover:bg-gradient-to-r hover:from-zinc-700 hover:via-zinc-800 hover:to-zinc-600">
<div class="group-hover:animate-spin-slow invisible absolute -top-40 -bottom-40 left-10 right-10 bg-gradient-to-r from-transparent via-gray-600 to-transparent group-hover:visible"></div> <div class="group-hover:animate-spin-slow invisible absolute -top-40 -bottom-40 left-10 right-10 bg-gradient-to-r from-transparent via-gray-600 to-transparent group-hover:visible"></div>
<div class="relative rounded-[15px] dark:bg-zinc-900 bg-zinc-100 dark:text-white text-accent-content p-6"> <div class="relative rounded-[15px] dark:bg-zinc-900 bg-zinc-100 dark:text-white text-accent-content p-6">
<div class="space-y-4"> <div class="space-y-4">
<flux:icon.clock /> <flux:icon.clock />
<p class="text-lg font-semibold dark:text-white text-accent-content">Fast and Anonymous Email Service</p> <p class="text-lg font-semibold dark:text-white text-accent-content">Fast and Anonymous Email Service</p>
<p class="font-md text-slate-500">Experience fast message delivery without delays or restrictions. Our service is finely tuned for maximum delivery speed, ensuring you stay connected seamlessly.</p> <p class="font-md text-slate-500">Experience fast message delivery without delays or restrictions. Zemail.me provides user with disposable gmail emails that can be used to avoid future spam and irrelevant marketing emails.</p>
</div> </div>
</div> </div>
</div> </div>
@@ -60,4 +75,32 @@
</div> </div>
</div> </div>
<flux:heading class="mt-10 mb-3 w-full text-center" size="xl" level="1">----- Popular Articles -----</flux:heading>
<div class="mb-3"></div>
<div class="flex justify-center items-center py-3">
<div class="flex justify-center items-center">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 p-1">
@foreach(config('app.blogs') as $blog)
<a wire:navigate href="/blog/{{ $blog->slug }}">
<div class="flex items-center">
<div class="group relative mx-auto w-96 overflow-hidden rounded-[16px] dark:bg-zinc-800 bg-zinc-200 p-[1px] ease-in-out hover:bg-gradient-to-r hover:from-zinc-600 hover:via-zinc-800 hover:to-zinc-700">
<div class="group-hover:animate-spin-slow invisible absolute -top-40 -bottom-40 left-10 right-10 bg-gradient-to-r from-transparent via-gray-600 to-transparent group-hover:visible"></div>
<div class="relative rounded-[15px] dark:bg-zinc-900 bg-zinc-100 dark:text-white text-accent-content p-6">
<div class="space-y-4">
<p class="font-md text-slate-500">
<img src="/{{ $blog->post_image }}" class="card-img-top" alt="{{ $blog->slug }}">
</p>
<p class="text-lg font-semibold dark:text-white text-accent-content truncate">{{ $blog->post }}</p>
</div>
</div>
</div>
</div>
</a>
@endforeach
</div>
</div>
</div>
</div> </div>

View File

@@ -0,0 +1,31 @@
@section('title'){{ $page->title }} | {{ config('app.settings.app_name') }}@endsection
@section('metas')
@forelse ($page->meta as $key => $value)
@if ($value)
@if ($key == "description")
@section('description'){{ $value }}@endsection
@elseif($key == "keywords")
@section('keywords'){{ $value }}@endsection
@else
<meta name="{{ $key }}" content="{{ $value }}">
@endif
@endif
@empty
@endforelse
@endsection
@section('custom_header')
@if(!empty($page->custom_header))
{!! $page->custom_header !!}
@endif
@endsection
<div>
<flux:heading class="mb-3 truncate" size="xl" level="1">{{ $page->title }}</flux:heading>
<div class="mb-3"></div>
<div class="block rounded-lg bg-white shadow-md dark:bg-zinc-700 items-center p-1">
<div class="flex w-full items-center justify-center px-4 py-4 sm:px-6">
<flux:text>{!! $page->content !!}</flux:text>
</div>
</div>
</div>

View File

@@ -19,3 +19,7 @@ Schedule::call(function () {
Schedule::call(function () { Schedule::call(function () {
Email::deleteBulkMailboxes(); Email::deleteBulkMailboxes();
})->everyMinute(); })->everyMinute();
Schedule::call(function () {
Email::deleteMessagesFromDB();
})->everyMinute();

View File

@@ -1,8 +1,11 @@
<?php <?php
use App\Http\Controllers\AppController; use App\Http\Controllers\AppController;
use App\Http\Middleware\CheckPageSlug;
use App\Livewire\Blog;
use App\Livewire\Frontend\Mailbox; use App\Livewire\Frontend\Mailbox;
use App\Livewire\Home; use App\Livewire\Home;
use App\Livewire\Page;
use App\Models\ZEmail; use App\Models\ZEmail;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@@ -13,6 +16,8 @@ Route::get('/switch/{email}', [AppController::class, 'switch'])->name('switch');
Route::get('/delete/{email?}', [AppController::class, 'delete'])->name('delete'); Route::get('/delete/{email?}', [AppController::class, 'delete'])->name('delete');
Route::get('locale/{locale}', [AppController::class, 'locale'])->name('locale'); Route::get('locale/{locale}', [AppController::class, 'locale'])->name('locale');
Route::get('/blog/{slug}', Blog::class)->name('blog');
Route::get('/msg/{email?}/', function ($email) { Route::get('/msg/{email?}/', function ($email) {
$responses = [ $responses = [
@@ -37,3 +42,5 @@ Route::get('/del', function () {
dd(\App\Models\Email::mailToDBStatus()); dd(\App\Models\Email::mailToDBStatus());
return \App\Models\Email::mailToDBStatus(); return \App\Models\Email::mailToDBStatus();
}); });
Route::get('{slug}', Page::class)->where('slug', '.*')->name('page')->middleware(CheckPageSlug::class);