firstcommit

This commit is contained in:
2025-08-17 16:23:14 +05:45
commit 76bf4c0a18
2648 changed files with 362795 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
<?php
namespace Modules\ContactUs\app\Http\Controllers;
use App\Mail\ReplyToMail;
use App\Jobs\ReplyToMailJob;
use Illuminate\Http\Request;
use App\Services\LogoService;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Modules\ContactUs\app\Models\ContactUs;
use Modules\ContactUs\app\Repositories\ContactUsRepository;
use Modules\ContactUs\app\Http\Requests\CreateContactUsRequest;
class ContactUsController extends Controller
{
protected $contactUsRepository;
public function __construct()
{
$this->contactUsRepository = new ContactUsRepository;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$perPage = $request->has('per-page') ? $request->input('per-page') : null;
$filter = $request->has('filter') ? $request->input('filter') : [];
$data['contactUsList'] = $this->contactUsRepository->allContactList($perPage, $filter);
$data['contactUsCount'] = $data['contactUsList']->count();
// dd(($data['contactUsCount']));
return view('contactus::index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function replyToMail(LogoService $logoService, Request $request, $uuid)
{
$citizenEmail = ContactUs::where('uuid', $uuid)->first();
if (!$citizenEmail) {
return null;
}
dispatch(new ReplyToMailJob(
$citizenEmail,
$request->content,
$logoService->getSiteLogo()
));
return redirect()->route('cms.contactUs.index');
}
public function create()
{
return view('contactus::create');
}
/**
* Store a newly created resource in storage.
*/
public function store(CreateContactUsRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->contactUsRepository->storeContactUsList($validated);
toastr()->success('Contact detail created successfully.');
return redirect()->route('cms.contactus.index');
} catch (\Throwable $th) {
report($th);
toastr()->error('Something went wrong.');
return back();
}
}
/**
* Show the specified resource.
*/
public function show($uuid)
{
$data['contactUs'] = $this->contactUsRepository->findContactUsListById($uuid);
return view('contactus::show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('contactus::edit');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($uuid)
{
try {
$contact_us = $this->contactUsRepository->deleteContactUsList($uuid);
if (!$contact_us) {
toastr()->error('Contact detail not found.');
return back();
}
toastr()->success('Contact detail deleted successfully.');
return redirect()->route('cms.contactus.index');
} catch (\Throwable $th) {
report($th);
toastr()->error('Something went wrong.');
return back();
}
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Modules\ContactUs\app\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateContactUsRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
return [
'full_name' => 'required|string|max:200|regex:/^[a-zA-Z. ]+$/',
'address' => 'sometimes|nullable|string|max:200',
'email' => 'sometimes|nullable|email',
'subject' => 'sometimes|nullable|string|max:1000',
'message' => 'required|string|max:1000',
'phone' => 'sometimes|nullable|numeric|digits:10',
];
}
public function messages()
{
return [
'full_name.required' => 'The full name field is required.',
'full_name.string' => 'The full name must be a string.',
'full_name.max' => 'The full name may not be greater than 200 characters.',
'full_name.regex' => 'The full name may only contain letters, dots, and spaces.',
'address.string' => 'The address must be a string.',
'address.max' => 'The address may not be greater than 200 characters.',
'email.email' => 'Invalid email format.',
'subject.string' => 'The subject must be a string.',
'subject.max' => 'The subject may not be greater than 1000 characters.',
'message.required' => 'The message field is required.',
'message.string' => 'The message must be a string.',
'message.max' => 'The message may not be greater than 1000 characters.',
'phone.numeric' => 'The phone must be a number.',
'phone.digits' => 'The phone must be exactly 10 digits long.'
];
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
}

View File

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\ContactUs\app\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Modules\ContactUs\Database\factories\ContactUsFactory;
class ContactUs extends Model
{
// use HasFactory;
use SoftDeletes;
/**
* The attributes that are mass assignable.
*/
protected $fillable = [
'uuid',
'full_name',
'address',
'email',
'subject',
'message',
'phone',
];
protected static function newFactory(): ContactUsFactory
{
//return ContactUsFactory::new();
}
}

View File

View File

@@ -0,0 +1,114 @@
<?php
namespace Modules\ContactUs\app\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class ContactUsServiceProvider extends ServiceProvider
{
protected string $moduleName = 'ContactUs';
protected string $moduleNameLower = 'contactus';
/**
* Boot the application events.
*/
public function boot(): void
{
$this->registerCommands();
$this->registerCommandSchedules();
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations'));
}
/**
* Register the service provider.
*/
public function register(): void
{
$this->app->register(RouteServiceProvider::class);
}
/**
* Register commands in the format of Command::class
*/
protected function registerCommands(): void
{
// $this->commands([]);
}
/**
* Register command Schedules.
*/
protected function registerCommandSchedules(): void
{
// $this->app->booted(function () {
// $schedule = $this->app->make(Schedule::class);
// $schedule->command('inspire')->hourly();
// });
}
/**
* Register translations.
*/
public function registerTranslations(): void
{
$langPath = resource_path('lang/modules/'.$this->moduleNameLower);
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
$this->loadJsonTranslationsFrom($langPath);
} else {
$this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower);
$this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang'));
}
}
/**
* Register config.
*/
protected function registerConfig(): void
{
$this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower.'.php')], 'config');
$this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower);
}
/**
* Register views.
*/
public function registerViews(): void
{
$viewPath = resource_path('views/modules/'.$this->moduleNameLower);
$sourcePath = module_path($this->moduleName, 'resources/views');
$this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower.'-module-views']);
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
$componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.config('modules.paths.generator.component-class.path'));
Blade::componentNamespace($componentNamespace, $this->moduleNameLower);
}
/**
* Get the services provided by the provider.
*/
public function provides(): array
{
return [];
}
private function getPublishableViewPaths(): array
{
$paths = [];
foreach (config('view.paths') as $path) {
if (is_dir($path.'/modules/'.$this->moduleNameLower)) {
$paths[] = $path.'/modules/'.$this->moduleNameLower;
}
}
return $paths;
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace Modules\ContactUs\app\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* The module namespace to assume when generating URLs to actions.
*/
protected string $moduleNamespace = 'Modules\ContactUs\app\Http\Controllers';
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*/
public function boot(): void
{
parent::boot();
}
/**
* Define the routes for the application.
*/
public function map(): void
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*/
protected function mapWebRoutes(): void
{
Route::middleware('web')
->namespace($this->moduleNamespace)
->group(module_path('ContactUs', '/routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*/
protected function mapApiRoutes(): void
{
Route::prefix('api')
->middleware('api')
->namespace($this->moduleNamespace)
->group(module_path('ContactUs', '/routes/api.php'));
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace Modules\ContactUs\app\Repositories;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Modules\ContactUs\app\Models\ContactUs;
class ContactUsRepository
{
public function allContactList($perPage = null, $filter = [], $sort = ['by' => 'id', 'sort' => 'DESC'])
{
return ContactUs::when(array_keys($filter, true), function ($query) use ($filter) {
if (!empty($filter['email'])) {
$query->where('email', $filter['email']);
}
})
->orderBy($sort['by'], $sort['sort'])
->paginate($perPage ?: env('PAGE_LIMIT', 999));
}
public function findContactUsListById($uuid)
{
return ContactUs::where('uuid', $uuid)->first();
}
public function storeContactUsList($validated)
{
DB::beginTransaction();
try {
$contact_us = new ContactUs();
$contact_us->uuid = Str::uuid();
$contact_us->full_name = $validated['full_name'];
$contact_us->address = $validated['address'] ?? null;
$contact_us->email = $validated['email'] ?? null;
$contact_us->phone = $validated['phone'];
$contact_us->subject = $validated['subject'] ?? null;
$contact_us->message = $validated['message'];
$contact_us->save();
DB::commit();
return $contact_us;
} catch (\Throwable $th) {
report($th);
DB::rollback();
return null;
}
}
public function deleteContactUsList($uuid)
{
DB::beginTransaction();
try {
$contact_us = $this->findContactUsListById($uuid);
if (!$contact_us) {
return null;
}
$contact_us->delete();
DB::commit();
return true;
} catch (\Throwable $th) {
DB::rollback();
report($th);
return null;
}
}
}

View File

@@ -0,0 +1,31 @@
{
"name": "nwidart/contactus",
"description": "",
"authors": [
{
"name": "Nicolas Widart",
"email": "n.widart@gmail.com"
}
],
"extra": {
"laravel": {
"providers": [],
"aliases": {
}
}
},
"autoload": {
"psr-4": {
"Modules\\ContactUs\\": "",
"Modules\\ContactUs\\App\\": "app/",
"Modules\\ContactUs\\Database\\Factories\\": "database/factories/",
"Modules\\ContactUs\\Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Modules\\ContactUs\\Tests\\": "tests/"
}
}
}

View File

View File

@@ -0,0 +1,5 @@
<?php
return [
'name' => 'ContactUs',
];

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('contact_us', function (Blueprint $table) {
$table->id();
$table->uuid();
$table->string('full_name');
$table->string('address')->nullable();
$table->string('email')->nullable();
$table->string('subject')->nullable();
$table->string('message');
$table->string('phone');
$table->softDeletes();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('contact_us');
}
};

View File

@@ -0,0 +1,41 @@
<?php
namespace Modules\ContactUs\database\seeders;
use Illuminate\Support\Str;
use Illuminate\Database\Seeder;
use Modules\ContactUs\app\Models\ContactUs;
class ContactUsDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$contactUs = [
[
'full_name' => 'radha shyaka',
'address' => 'kathmandu, Nepal',
'email' => 'radhar@example.com',
'phone' => '9801234567',
'subject' => 'Hair transplant',
'message' => 'I wan to transplant hair. What should be process',
],
[
'full_name' => 'shyam shrestha',
'address' => 'lalitpur, Nepal',
'email' => 'shyam@example.com',
'phone' => '9801234566',
'message' => 'May i have detail about doctor for eyebrow tranplant.',
],
];
if (!empty($contactUs)) {
foreach ($contactUs as $data) {
$data['uuid'] = Str::uuid();
ContactUs::create($data);
}
}
}
}

View File

View File

@@ -0,0 +1,11 @@
{
"name": "ContactUs",
"alias": "contactus",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\ContactUs\\app\\Providers\\ContactUsServiceProvider"
],
"files": []
}

View File

@@ -0,0 +1,15 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"sass": "^1.69.5",
"postcss": "^8.3.7",
"vite": "^4.0.0"
}
}

View File

@@ -0,0 +1,128 @@
@extends('admin::layouts.master')
@section('title')
Contact Us List
@endsection
@section('breadcrumb')
@php
$breadcrumbData = [
[
'title' => 'Message',
'link' => 'null',
],
[
'title' => 'Dashboard',
'link' => route('dashboard'),
],
[
'title' => 'Contact Us Lists',
'link' => null,
],
];
@endphp
@include('admin::layouts.partials.breadcrumb', $breadcrumbData)
@endsection
@section('content')
<!-- banners List Table -->
<div class="card">
<div class="row">
<div class="col-md-6">
<h4 class="card-header">List of Message</h4>
</div>
{{-- <div class="col-md-6">
<div class="flex-column flex-md-row">
<div class="dt-action-buttons text-end pt-3 px-3">
<div class="dt-buttons btn-group flex-wrap">
<a href="{{ route('cms.banners.create') }}"
class="btn btn-secondary create-new btn-primary d-none d-sm-inline-block text-white">
<i class="bx bx-plus me-sm-1"></i>
Add New
</a>
</div>
</div>
</div>
</div> --}}
</div>
<div class="card-datatable table-responsive">
<table class="table">
<thead class="table-light">
<tr>
<th>S.N</th>
<th>Email With Message</th>
<th>Full Name</th>
<th>Address</th>
<th>Created At</th>
<th>Actions</th>
</tr>
</thead>
<tbody class="table-border-bottom-0">
@if ($contactUsCount > 0)
@foreach ($contactUsList ?? [] as $contact_us)
<tr>
<td>
#{{ $loop->iteration }}
</td>
<td>
<div class="d-flex align-items-center me-3">
<div class="card-title mb-0 px-3">
<h6 class="mb-0"> {{ $contact_us->email }}</h6>
<small class="text-muted">{{ Str::limit($contact_us->message, 80) }}</small>
</div>
</div>
</td>
<td>
{{ $contact_us->full_name }}
</td>
<td>
{{ $contact_us->address }}
</td>
<td>
{{ $contact_us->created_at->toFormattedDateString() }}
</td>
<td>
<div class="d-flex">
<form method="POST"
action="{{ route('cms.contactUs.show', ['uuid' => $contact_us->uuid]) }}"
class="dropdown-item">
@csrf
<button type="submit" class="border-0 bg-transparent viewBtn"
style="color:inherit"><i class="bx bx-show-alt me-1"></i></button>
</form>
<form method="POST"
action="{{ route('cms.contactUs.delete', ['uuid' => $contact_us->uuid]) }}"
id="deleteForm_{{ $contact_us->uuid }}" class="dropdown-item">
@csrf
@method('DELETE')
<button type="submit" class="border-0 bg-transparent deleteBtn"
style="color:inherit"><i class="bx bx-trash me-1"></i></button>
</form>
</div>
</td>
</tr>
@endforeach
@else
<tr>
<td colspan="7">No record found.</td>
</tr>
@endif
</tbody>
</table>
</div>
<div class="px-3">
{{-- {{ $contact_us->links('admin::layouts.partials.pagination') }} --}}
</div>
</div>
@endsection
{{-- style --}}
@push('required-styles')
@include('admin::vendor.dataTables.style')
@endpush
{{-- script --}}
@push('required-scripts')
@include('admin::vendor.dataTables.script')
@endpush

View File

@@ -0,0 +1,683 @@
@extends('admin::layouts.master')
@section('title')
Contact Us List
@endsection
@section('breadcrumb')
@php
$breadcrumbData = [
[
'title' => 'Message',
'link' => 'null',
],
[
'title' => 'Dashboard',
'link' => route('dashboard'),
],
[
'title' => 'Contact Us Lists',
'link' => null,
],
];
@endphp
@include('admin::layouts.partials.breadcrumb', $breadcrumbData)
@endsection
@section('content')
<div class="container-xxl flex-grow-1 container-p-y">
<div class="app-email card">
<div class="border-0">
<div class="row g-0">
<!-- Email Sidebar -->
<div class="col app-email-sidebar border-end flex-grow-0" id="app-email-sidebar">
<div class="btn-compost-wrapper d-grid">
<button class="btn btn-primary btn-compose" data-bs-toggle="modal"
data-bs-target="#emailComposeSidebar">
Compose
</button>
</div>
<!-- Email Filters -->
<div class="email-filters py-2">
<!-- Email Filters: Folder -->
<ul class="email-filter-folders list-unstyled mb-4">
<li class="active d-flex justify-content-between" data-target="inbox">
<a href="javascript:void(0);" class="d-flex flex-wrap align-items-center">
<i class="bx bx-envelope"></i>
<span class="align-middle ms-2">Inbox</span>
</a>
<div class="badge bg-label-primary rounded-pill">{{ $contactUsCount ?? '0' }}</div>
</li>
<li class="d-flex" data-target="sent">
<a href="javascript:void(0);" class="d-flex flex-wrap align-items-center">
<i class="bx bx-paper-plane"></i>
<span class="align-middle ms-2">Sent</span>
</a>
</li>
<li class="d-flex" data-target="draft">
<a href="javascript:void(0);" class="d-flex flex-wrap align-items-center">
<i class="bx bx-pencil"></i>
<span class="align-middle ms-2">Draft</span>
</a>
</li>
<li class="d-flex justify-content-between" data-target="starred">
<a href="javascript:void(0);" class="d-flex flex-wrap align-items-center">
<i class="bx bx-star"></i>
<span class="align-middle ms-2">Starred</span>
</a>
<div class="badge bg-label-warning rounded-pill">10</div>
</li>
<li class="d-flex align-items-center" data-target="spam">
<a href="javascript:void(0);" class="d-flex flex-wrap align-items-center">
<i class="bx bx-error-circle"></i>
<span class="align-middle ms-2">Spam</span>
</a>
</li>
<li class="d-flex align-items-center" data-target="trash">
<a href="javascript:void(0);" class="d-flex flex-wrap align-items-center">
<i class="bx bx-trash"></i>
<span class="align-middle ms-2">Trash</span>
</a>
</li>
</ul>
<!-- Email Filters: Labels -->
{{-- <div class="email-filter-labels">
<small class="fw-normal text-uppercase text-muted m-4">Labels</small>
<ul class="list-unstyled mb-0">
<li data-target="work">
<a href="javascript:void(0);">
<i class="badge badge-dot bg-success"></i>
<span class="align-middle ms-2">Work</span>
</a>
</li>
<li data-target="company">
<a href="javascript:void(0);">
<i class="badge badge-dot bg-primary"></i>
<span class="align-middle ms-2">Company</span>
</a>
</li>
<li data-target="important">
<a href="javascript:void(0);">
<i class="badge badge-dot bg-info"></i>
<span class="align-middle ms-2">Important</span>
</a>
</li>
<li data-target="private">
<a href="javascript:void(0);">
<i class="badge badge-dot bg-danger"></i>
<span class="align-middle ms-2">Private</span>
</a>
</li>
</ul>
</div> --}}
<!--/ Email Filters -->
</div>
</div>
<!--/ Email Sidebar -->
<!-- Emails List -->
<div class="col app-emails-list">
<div class="card shadow-none border-0">
<div class="card-body emails-list-header p-3 py-lg-3 py-2">
<!-- Email List: Search -->
<div class="d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center w-100">
<i class="bx bx-menu bx-sm cursor-pointer d-block d-lg-none me-3"
data-bs-toggle="sidebar" data-target="#app-email-sidebar" data-overlay></i>
<div class="mb-0 mb-lg-2 w-100">
<div class="input-group input-group-merge shadow-none">
<span class="input-group-text border-0 ps-0" id="email-search">
<i class="bx bx-search fs-4"></i>
</span>
<input type="text" class="form-control email-search-input border-0"
placeholder="Search mail" aria-label="Search mail"
aria-describedby="email-search" />
</div>
</div>
</div>
<div class="d-flex align-items-center mb-0 mb-md-2">
<i
class="bx bx-rotate-left scaleX-n1-rtl cursor-pointer email-refresh me-2 bx-sm"></i>
<div class="dropdown">
<i class="bx bx-dots-vertical-rounded cursor-pointer bx-sm" id="emailsActions"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</i>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="emailsActions">
<a class="dropdown-item" href="javascript:void(0)">Mark as read</a>
<a class="dropdown-item" href="javascript:void(0)">Mark as unread</a>
<a class="dropdown-item" href="javascript:void(0)">Delete</a>
<a class="dropdown-item" href="javascript:void(0)">Archive</a>
</div>
</div>
</div>
</div>
<hr class="mx-n3 emails-list-header-hr" />
<!-- Email List: Actions -->
<div class="d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<div class="form-check me-2 mb-0">
<input class="form-check-input" type="checkbox" id="email-select-all" />
<label class="form-check-label" for="email-select-all"></label>
</div>
<i class="bx bx-trash-alt email-list-delete cursor-pointer me-2"></i>
<i class="bx bx-envelope-open email-list-read cursor-pointer me-2"></i>
<div class="dropdown me-2">
<i class="bx bx-folder cursor-pointer" id="dropdownMenuFolder"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></i>
<div class="dropdown-menu dropdown-menu-end"
aria-labelledby="dropdownMenuFolder">
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-error-circle bx-xs me-1"></i>
<span class="align-middle">Spam</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-pencil bx-xs me-1"></i>
<span class="align-middle">Draft</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-trash bx-xs me-1"></i>
<span class="align-middle">Trash</span>
</a>
</div>
</div>
<div class="dropdown">
<i class="bx bx-purchase-tag cursor-pointer" id="dropdownLabel"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</i>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="dropdownLabel">
<a class="dropdown-item" href="javascript:void(0)">
<i class="badge badge-dot bg-success"></i>
<span class="align-middle">Workshop</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="badge badge-dot bg-primary"></i>
<span class="align-middle">Company</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="badge badge-dot bg-info"></i>
<span class="align-middle">Important</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="badge badge-dot bg-danger"></i>
<span class="align-middle">Private</span>
</a>
</div>
</div>
</div>
<div
class="email-pagination d-sm-flex d-none align-items-center flex-wrap justify-content-between justify-sm-content-end">
<span class="d-sm-block d-none mx-3 text-muted">1-10 of 653</span>
<i
class="email-prev bx bx-chevron-left scaleX-n1-rtl cursor-pointer text-muted me-2 fs-4"></i>
<i class="email-next bx bx-chevron-right scaleX-n1-rtl cursor-pointer fs-4"></i>
</div>
</div>
</div>
<hr class="container-m-nx m-0" />
<!-- Email List: Items -->
<div class="email-list pt-0">
<ul class="list-unstyled m-0">
@if ($contactUsList->isNotEmpty())
@foreach ($contactUsList as $contactUs)
<li class="email-list-item" data-starred="true" data-bs-toggle="sidebar"
data-target="#app-email-view-{{ $contactUs->id }}">
<div class="d-flex align-items-center">
<div class="form-check mb-0">
<input class="email-list-item-input form-check-input"
type="checkbox" id="email-1" />
<label class="form-check-label" for="email-1"></label>
</div>
<i
class="email-list-item-bookmark bx bx-star d-sm-inline-block d-none cursor-pointer ms-2 me-3"></i>
{{-- <img src="../../assets/img/avatars/1.png" alt="user-avatar"
class="d-block flex-shrink-0 rounded-circle me-sm-3 me-0"
height="32" width="32" /> --}}
<div class="email-list-item-content ms-2 ms-sm-0 me-2">
<span
class="email-list-item-username me-2">{{ $contactUs->full_name }}</span>
<span class="email-list-item-subject d-xl-inline-block d-block">
{!! Str::limit($contactUs->message, 50, '...') !!}
</span>
</div>
<div class="email-list-item-meta ms-auto d-flex align-items-center">
<span
class="email-list-item-label badge badge-dot bg-danger d-none d-md-inline-block me-2"
data-label="private"></span>
<small class="email-list-item-time text-muted"
style="width:90px !Important;">{{ $contactUs->created_at->toFormattedDateString() }}</small>
<ul class="list-inline email-list-item-actions">
<li class="list-inline-item email-read"><i
class="bx bx-envelope-open"></i></li>
<li class="list-inline-item email-delete"><i
class="bx bx-trash"></i>
</li>
<li class="list-inline-item"><i class="bx bx-archive-in"></i>
</li>
</ul>
</div>
</div>
</li>
@endforeach
@endif
</ul>
</div>
</div>
<div class="app-overlay"></div>
</div>
<!-- /Emails List -->
<!-- Email View -->
@if ($contactUsList->isNotEmpty())
@foreach ($contactUsList as $contactUs)
<div class="col app-email-view flex-grow-0 bg-body" id="app-email-view-{{ $contactUs->id }}">
<div class="card shadow-none border-0 rounded-0 app-email-view-header px-3 py-md-3 py-2">
<!-- Email View : Title bar-->
<div class="d-flex justify-content-between align-items-center py-2">
<div class="d-flex align-items-center overflow-hidden">
<i class="bx bx-chevron-left bx-sm cursor-pointer me-2"
data-bs-toggle="sidebar"
data-target="#app-email-view-{{ $contactUs->id }}i"></i>
<h6 class="text-truncate mb-0 me-2">Focused impactful open issues</h6>
<span class="badge bg-label-danger">Private</span>
</div>
<!-- Email View : Action bar-->
<div class="d-flex align-items-center">
<i class="bx bx-printer d-sm-block d-none"></i>
<div class="dropdown ms-3">
<i class="bx bx-dots-vertical-rounded cursor-pointer"
id="dropdownMoreOptions" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
</i>
<div class="dropdown-menu dropdown-menu-end"
aria-labelledby="dropdownMoreOptions">
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-envelope-open bx-xs me-1"></i>
<span class="align-middle">Mark as unread</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-envelope-open bx-xs me-1"></i>
<span class="align-middle">Mark as unread</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-star bx-xs me-1"></i>
<span class="align-middle">Add star</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-calendar bx-xs me-1"></i>
<span class="align-middle">Create Event</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-volume-mute bx-xs me-1"></i>
<span class="align-middle">Mute</span>
</a>
<a class="dropdown-item d-sm-none d-block" href="javascript:void(0)">
<i class="bx bx-printer bx-xs me-1"></i>
<span class="align-middle">Print</span>
</a>
</div>
</div>
</div>
</div>
<hr class="app-email-view-hr mx-n3 mb-2" />
<div class="d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<i class="bx bx-trash-alt cursor-pointer me-3" data-bs-toggle="sidebar"
data-target="#app-email-view"></i>
<i class="bx bx-envelope-open cursor-pointer me-3"></i>
<div class="dropdown me-3">
<i class="bx bx-folder cursor-pointer" id="dropdownMenuFolder"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</i>
<div class="dropdown-menu dropdown-menu-end"
aria-labelledby="dropdownMenuFolder">
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-error-circle bx-xs me-1"></i>
<span class="align-middle">Spam</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-pencil bx-xs me-1"></i>
<span class="align-middle">Draft</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-trash bx-xs me-1"></i>
<span class="align-middle">Trash</span>
</a>
</div>
</div>
<div class="dropdown me-3">
<i class="bx bx-purchase-tag cursor-pointer" id="dropdownLabel"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</i>
<div class="dropdown-menu dropdown-menu-end"
aria-labelledby="dropdownLabel">
<a class="dropdown-item" href="javascript:void(0)">
<i class="badge badge-dot bg-success"></i>
<span class="align-middle">Workshop</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="badge badge-dot bg-primary"></i>
<span class="align-middle">Company</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="badge badge-dot bg-info"></i>
<span class="align-middle">Important</span>
</a>
</div>
</div>
</div>
<div class="d-flex align-items-center flex-wrap justify-content-end">
<span class="d-sm-block d-none mx-3 text-muted">1-10 of 653</span>
<i
class="bx bx-chevron-left scaleX-n1-rtl cursor-pointer text-muted me-2 fs-4"></i>
<i class="bx bx-chevron-right scaleX-n1-rtl cursor-pointer fs-4"></i>
</div>
</div>
</div>
<hr class="m-0" />
<!-- Email View : Content-->
<div class="app-email-view-content py-4">
<p class="email-earlier-msgs text-center text-muted cursor-pointer mb-5">1 Earlier
Message</p>
<!-- Email View : Previous mails-->
<div class="card email-card-prev mx-sm-4 mx-3 border shadow-none">
<div
class="card-header d-flex justify-content-between align-items-center flex-wrap">
<div class="d-flex align-items-center mb-sm-0 mb-3">
<img src="../../assets/img/avatars/2.png" alt="user-avatar"
class="flex-shrink-0 rounded-circle me-3" height="40"
width="40" />
<div class="flex-grow-1 ms-1">
<h6 class="m-0">Ross Geller</h6>
<small class="text-muted">rossGeller@email.com</small>
</div>
</div>
<div class="d-flex align-items-center">
<p class="mb-0 me-3 text-muted">June 20th 2020, 08:30 AM</p>
<i class="bx bx-paperclip cursor-pointer me-2 fs-4"></i>
<i
class="email-list-item-bookmark bx bx-star cursor-pointer me-2 fs-4"></i>
<div class="dropdown me-3">
<i class="bx bx-dots-vertical-rounded cursor-pointer fs-4"
id="dropdownEmail" data-bs-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
</i>
<div class="dropdown-menu dropdown-menu-end"
aria-labelledby="dropdownEmail">
<a class="dropdown-item scroll-to-reply"
href="javascript:void(0)">
<i class="bx bx-share me-1"></i>
<span class="align-middle">Reply</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-share me-1 scaleX-n1 scaleX-n1-rtl"></i>
<span class="align-middle">Forward</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-info-circle me-1"></i>
<span class="align-middle">Report</span>
</a>
</div>
</div>
</div>
</div>
<div class="card-body">
<p class="fw-bold">Greetings!</p>
<p>
It is a long established fact that a reader will be distracted by the
readable
content of
a page when looking at its layout.The point of using Lorem Ipsum is that it
has a
more-or-less normal distribution of letters, as opposed to using 'Content
here,
content
here',making it look like readable English.
</p>
<p>
There are many variations of passages of Lorem Ipsum available, but the
majority
have
suffered alteration in some form, by injected humour, or randomised words
which
don't look
even slightly believable.
</p>
<p class="mb-0">Sincerely yours,</p>
<p class="fw-bold mb-0">Envato Design Team</p>
<hr />
<p class="email-attachment-title mb-2">Attachments</p>
<div class="cursor-pointer">
<i class="bx bx-file"></i>
<span class="align-middle ms-1">report.xlsx</span>
</div>
</div>
</div>
<!-- Email View : Last mail-->
<div class="card email-card-last mx-sm-4 mx-3 mt-4 border shadow-none">
<div
class="card-header d-flex justify-content-between align-items-center flex-wrap">
<div class="d-flex align-items-center mb-sm-0 mb-3">
{{-- <img src="../../assets/img/avatars/1.png" alt="user-avatar"
class="flex-shrink-0 rounded-circle me-3" height="40"
width="40" /> --}}
<div class="flex-grow-1 ms-1">
<h6 class="m-0">{{ $contactUs->full_name }}</h6>
<small class="text-muted">{{ $contactUs->email }}</small>
</div>
</div>
<div class="d-flex align-items-center">
<p class="mb-0 me-3 text-muted">
{{ $contactUs->created_at->toFormattedDateString() }}</p>
<i class="bx bx-paperclip cursor-pointer me-2 fs-4"></i>
<i
class="email-list-item-bookmark bx bx-star cursor-pointer me-2 fs-4"></i>
<div class="dropdown me-3">
<i class="bx bx-dots-vertical-rounded cursor-pointer fs-4"
id="dropdownEmail" data-bs-toggle="dropdown" aria-haspopup="true"
aria-expanded="false"></i>
<div class="dropdown-menu dropdown-menu-end"
aria-labelledby="dropdownEmail">
<a class="dropdown-item scroll-to-reply"
href="javascript:void(0)">
<i class="bx bx-share me-1"></i>
<span class="align-middle">Reply</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-share me-1 scaleX-n1 scaleX-n1-rtl"></i>
<span class="align-middle">Forward</span>
</a>
<a class="dropdown-item" href="javascript:void(0)">
<i class="bx bx-info-circle me-1"></i>
<span class="align-middle">Report</span>
</a>
</div>
</div>
</div>
</div>
<div class="card-body">
{{ $contactUs->message }}
</div>
</div>
<!-- Email View : Reply mail-->
<div class="email-reply card mt-4 mx-sm-4 mx-3 border shadow-none">
<h6 class="card-header border-0">Reply to Ross Geller</h6>
<form action="{{ route('cms.contactUs.replyMail', $contactUs->uuid) }}" method="POST">
@csrf
<div class="card-body pt-0 px-3">
<div class="mb-3 col-md-12">
<label class="form-label" for="basic-default-message">Content</label>
<textarea name="" id="mainTextarea" class="d-none" style="display: none">dsdsf</textarea>
<textarea name="content" class="form-control full-editor" id="editorTextarea" rows='10'
placeholder="Algarves Benagil Cave beach is one of those extra special ones. The only way in is by kayaking or paddle boating, which obviously adds a more elusive touch to this already amazing place. ....."></textarea>
</div>
<div class="email-reply-editor"></div>
<div class="d-flex justify-content-end align-items-center">
<div class="cursor-pointer me-3">
<i class="bx bx-paperclip"></i>
<span class="align-middle">Attachments</span>
</div>
<button class="btn btn-primary">
<i class="bx bx-paper-plane me-1"></i>
<span class="align-middle">Send</span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
@endforeach
@endif
<!-- Email View -->
</div>
</div>
<!-- Compose Email -->
<div class="app-email-compose modal" id="emailComposeSidebar" tabindex="-1"
aria-labelledby="emailComposeSidebarLabel" aria-hidden="true">
<div class="modal-dialog m-0 me-md-4 mb-4 modal-lg">
<div class="modal-content p-0">
<div class="modal-header py-3">
<h5 class="modal-title fs-5">Compose Mail</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body flex-grow-1 pb-sm-0 p-4 py-2">
<form class="email-compose-form">
<div class="email-compose-to d-flex justify-content-between align-items-center">
<label class="form-label mb-0" for="emailContacts">To:</label>
<div class="select2-primary border-0 shadow-none flex-grow-1 mx-2">
<select class="select2 select-email-contacts form-select" id="emailContacts"
name="emailContacts" multiple>
<option data-avatar="1.png" value="Jane Foster">Jane Foster</option>
<option data-avatar="3.png" value="Donna Frank">Donna Frank</option>
<option data-avatar="5.png" value="Gabrielle Robertson">Gabrielle Robertson
</option>
<option data-avatar="7.png" value="Lori Spears">Lori Spears</option>
<option data-avatar="9.png" value="Sandy Vega">Sandy Vega</option>
<option data-avatar="11.png" value="Cheryl May">Cheryl May</option>
</select>
</div>
<div class="email-compose-toggle-wrapper">
<a class="email-compose-toggle-cc" href="javascript:void(0);">Cc |</a>
<a class="email-compose-toggle-bcc" href="javascript:void(0);">Bcc</a>
</div>
</div>
<div class="email-compose-cc d-none">
<hr class="mx-n4 my-2" />
<div class="d-flex align-items-center">
<label for="email-cc" class="form-label mb-0">Cc:</label>
<input type="text" class="form-control border-0 shadow-none flex-grow-1 mx-2"
id="email-cc" placeholder="someone@email.com" />
</div>
</div>
<div class="email-compose-bcc d-none">
<hr class="mx-n4 my-2" />
<div class="d-flex align-items-center">
<label for="email-bcc" class="form-label mb-0">Bcc:</label>
<input type="text" class="form-control border-0 shadow-none flex-grow-1 mx-2"
id="email-bcc" placeholder="someone@email.com" />
</div>
</div>
<hr class="mx-n4 my-2" />
<div class="email-compose-subject d-flex align-items-center mb-2">
<label for="email-subject" class="form-label mb-0">Subject:</label>
<input type="text" class="form-control border-0 shadow-none flex-grow-1 mx-2"
id="email-subject" placeholder="Project Details" />
</div>
<div class="email-compose-message mx-n4">
<div class="d-flex justify-content-end">
<div class="email-editor-toolbar border-bottom-0 w-100">
<span class="ql-formats me-0">
<button class="ql-bold"></button>
<button class="ql-italic"></button>
<button class="ql-underline"></button>
<button class="ql-list" value="ordered"></button>
<button class="ql-list" value="bullet"></button>
<button class="ql-link"></button>
<button class="ql-image"></button>
</span>
</div>
</div>
<div class="email-editor"></div>
</div>
<hr class="mx-n4 mt-0 mb-2" />
<div
class="email-compose-actions d-flex justify-content-between align-items-center mt-3 mb-3">
<div class="d-flex align-items-center">
<div class="btn-group">
<button type="reset" class="btn btn-primary" data-bs-dismiss="modal"
aria-label="Close">
Send
</button>
<button type="button"
class="btn btn-primary dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="javascript:void(0);">Schedule send</a>
</li>
<li><a class="dropdown-item" href="javascript:void(0);">Save draft</a>
</li>
</ul>
</div>
<label for="attach-file"><i
class="bx bx-paperclip cursor-pointer ms-2"></i></label>
<input type="file" name="file-input" class="d-none" id="attach-file" />
</div>
<div class="d-flex align-items-center">
<div class="dropdown">
<i class="bx bx-dots-vertical-rounded cursor-pointer"
data-bs-toggle="dropdown" aria-expanded="false"></i>
<ul class="dropdown-menu" aria-labelledby="dropdownMoreActions">
<li><button type="button" class="dropdown-item">Add Label</button></li>
<li><button type="button" class="dropdown-item">Plain text mode</button>
</li>
<li>
<hr class="dropdown-divider" />
</li>
<li><button type="button" class="dropdown-item">Print</button></li>
<li><button type="button" class="dropdown-item">Check Spelling</button>
</li>
</ul>
</div>
<button type="reset" class="btn" data-bs-dismiss="modal"
aria-label="Close">
<i class="bx bx-trash"></i>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- /Compose Email -->
</div>
</div>
<!-- / Content --
@endsection
{{-- style --}}
@push('required-styles')
@include('admin::vendor.full_editor.style')
@include('admin::vendor.dataTables.style')
@include('admin::vendor.mail.style')
@endpush
{{-- script --}}
@push('required-scripts')
@include('admin::vendor.textareaContentDisplay.script')
@include('admin::vendor.full_editor.script')
@include('admin::vendor.dataTables.script')
@include('admin::vendor.mail.script')
@endpush

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ContactUs Module - {{ config('app.name', 'Laravel') }}</title>
<meta name="description" content="{{ $description ?? '' }}">
<meta name="keywords" content="{{ $keywords ?? '' }}">
<meta name="author" content="{{ $author ?? '' }}">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
{{-- Vite CSS --}}
{{-- {{ module_vite('build-contactus', 'resources/assets/sass/app.scss') }} --}}
</head>
<body>
@yield('content')
{{-- Vite JS --}}
{{-- {{ module_vite('build-contactus', 'resources/assets/js/app.js') }} --}}
</body>

View File

@@ -0,0 +1,77 @@
@extends('admin::layouts.master')
@section('title')
Contact Us Message
@endsection
@section('breadcrumb')
@php
$breadcrumbData = [
[
'title' => 'Contact Us Message',
'link' => 'null',
],
[
'title' => 'Dashboard',
'link' => route('dashboard'),
],
[
'title' => 'Contact Us Message',
'link' => null,
],
];
@endphp
@include('admin::layouts.partials.breadcrumb', $breadcrumbData)
@endsection
@section('content')
<!-- banners List Table -->
<div class="card">
<div class="row">
<div class="col-md-6">
<h4 class="card-header">Contact Us Message</h4>
</div>
</div>
<div class="card">
<div class="card-header">
<h5> Message Send By {{ $contactUs->full_name ?? 'N/A' }}</h5>
</div>
<div class="modal-body">
<table class="table">
<tbody>
<tr>
<th>Name:</th>
<td>{{ $contactUs->full_name ?? 'N/A' }}</td>
</tr>
<tr>
<th>Address:</th>
<td>{{ $contactUs->address ?? 'N/A' }}</td>
</tr>
<tr>
<th>Email:</th>
<td>{{ $contactUs->email ?? 'N/A' }}</td>
</tr>
<tr>
<th>Phone No.:</th>
<td>{{ $contactUs->phone ?? 'N/A' }}</td>
</tr>
<tr>
<th>Subject:</th>
<td>{{ $contactUs->subject ?? 'N/A' }}</td>
</tr>
<tr>
<th>Message:</th>
<td>{{ $contactUs->message ?? 'N/A' }}</td>
</tr>
</tbody>
</table>
</div>
<div class="card-footer">
<a href="{{ route('cms.contactUs.index') }}" class="btn btn-secondary">Close</a>
</div>
</div>
</div>
@endsection

View File

View File

@@ -0,0 +1,19 @@
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware(['auth:sanctum'])->prefix('v1')->name('api.')->group(function () {
Route::get('contactus', fn (Request $request) => $request->user())->name('contactus');
});

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\ContactUs\app\Http\Controllers\ContactUsController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::group(
[
'prefix' => 'apanel',
'middleware' => ['auth'],
'as' => 'cms.',
],
function () {
Route::group(
[
'prefix' => 'cms',
'as' => 'contactUs.',
'controller' => 'ContactUsController',
],
function () {
Route::get('contact-us', 'index')->name('index');
Route::post('contact-us/{uuid}', 'show')->name('show');
// Route::post('contact-us/reply/{uuid}', 'replyToMail')->name('replyMail');
Route::delete('contact-us/{uuid}/delete', 'destroy')->name('delete');
}
);
}
);

View File

View File

View File

@@ -0,0 +1,26 @@
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
build: {
outDir: '../../public/build-contactus',
emptyOutDir: true,
manifest: true,
},
plugins: [
laravel({
publicDirectory: '../../public',
buildDirectory: 'build-contactus',
input: [
__dirname + '/resources/assets/sass/app.scss',
__dirname + '/resources/assets/js/app.js'
],
refresh: true,
}),
],
});
//export const paths = [
// 'Modules/$STUDLY_NAME$/resources/assets/sass/app.scss',
// 'Modules/$STUDLY_NAME$/resources/assets/js/app.js',
//];