diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index cbebc98d..9436fcdf 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -2,10 +2,12 @@ namespace App\Http\Controllers; +use App\Http\Requests\ContactSubmitRequest; use App\Models\Attachment; use App\Models\Category; use App\Models\Clip; use App\Models\Comment; +use App\Models\Contact; use App\Models\Customer; use App\Models\Gallery; use App\Models\Group; @@ -411,6 +413,24 @@ public function compare() $products = Product::whereIn('id', $ids)->where('status', 1)->get(); return view('client.default-list', compact('area', 'products', 'title', 'subtitle')); } + public function contact() + { + $area = 'contact-us'; + $title = __("Contact us"); + $subtitle = ''; + return view('client.default-list', compact('area', 'title', 'subtitle')); + } + public function sendContact(ContactSubmitRequest $request) + { + $con = new Contact(); + $con->name = $request->full_name; + $con->email = $request->email; + $con->mobile = $request->phone; + $con->subject = $request->subject; + $con->body = $request->bodya; + $con->save(); + return redirect()->back()->with(['message' => __('Your message has been successfully sent.')]); + } public function signOut() diff --git a/app/Http/Requests/ContactSubmitRequest.php b/app/Http/Requests/ContactSubmitRequest.php new file mode 100644 index 00000000..9f2cbd03 --- /dev/null +++ b/app/Http/Requests/ContactSubmitRequest.php @@ -0,0 +1,32 @@ +<?php + +namespace App\Http\Requests; + +use Illuminate\Foundation\Http\FormRequest; + +class ContactSubmitRequest extends FormRequest +{ + /** + * Determine if the user is authorized to make this request. + */ + public function authorize(): bool + { + return true; + } + + /** + * Get the validation rules that apply to the request. + * + * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> + */ + public function rules(): array + { + return [ + 'full_name' => ['required', 'string', 'max:255', 'min:3'], + 'phone' => ['required', 'string', 'max:15', 'min:8'], + 'subject' => ['nullable', 'string', 'max:255', 'min:4'], + 'email' => ['required', 'email', 'max:255', 'min:4'], + 'bodya' => ['required', 'string', 'max:4048', 'min:15'], + ]; + } +} diff --git a/app/Models/Area.php b/app/Models/Area.php index 8431430f..71d87164 100644 --- a/app/Models/Area.php +++ b/app/Models/Area.php @@ -18,6 +18,7 @@ class Area extends Model // 'categories_page', 'category', 'comments', + 'contact', 'clip', 'clips', 'clips_page', diff --git a/database/seeders/AreaSeeder.php b/database/seeders/AreaSeeder.php index 12c00138..9e193adf 100644 --- a/database/seeders/AreaSeeder.php +++ b/database/seeders/AreaSeeder.php @@ -45,7 +45,7 @@ public function run(): void [ 'name' => 'default_footer', 'valid_segments' => json_encode( - ["footer", "other", "ads" , "groups"] + ["footer", "other", "ads", "groups"] ), 'max' => 2, 'preview' => null, @@ -229,7 +229,7 @@ public function run(): void "parallax", "other", "register", "ads"] ), 'max' => 6, - 'preview' => 'client.register', + 'preview' => 'client.sign-up', 'icon' => 'ri-user-add-line', ], [ @@ -261,6 +261,16 @@ public function run(): void 'preview' => null, 'icon' => 'ri-scales-3-line', ], + [ + 'name' => 'contact-us', + 'valid_segments' => json_encode( + ["top", "header", "footer", "menu", + "parallax", "other", "contact", "ads", "index"] + ), + 'max' => 4, + 'preview' => null, + 'icon' => 'ri-mail-open-line', + ], ]; foreach ($areas as $area) { @@ -270,7 +280,7 @@ public function run(): void $a->valid_segments = $area['valid_segments']; $a->icon = $area['icon']; $a->preview = $area['preview']; - if ($area['name'] == 'index'){ + if ($area['name'] == 'index') { $a->use_default = false; } $a->save(); diff --git a/database/seeders/PartSeeder.php b/database/seeders/PartSeeder.php index eca39b46..4ec0f273 100644 --- a/database/seeders/PartSeeder.php +++ b/database/seeders/PartSeeder.php @@ -257,6 +257,15 @@ public function run(): void $part->sort = 1; $part->save(); + // ------------------------------------------------------------- + + $part = new Part(); + $part->segment = 'contact'; + $part->part = 'MeloContact'; + $part->area_id = Area::where('name', 'contact-us')->first()->id; + $part->sort = 1; + $part->save(); + } } diff --git a/resources/js/client-custom/safeForm.js b/resources/js/client-custom/safeForm.js index 6a6514d4..dd90f943 100644 --- a/resources/js/client-custom/safeForm.js +++ b/resources/js/client-custom/safeForm.js @@ -1,6 +1,7 @@ window.addEventListener('load',function () { setTimeout(()=>{ - document.querySelectorAll('.safe-from')?.forEach(function (el) { + document.querySelectorAll('.safe-form')?.forEach(function (el) { + const url = el.querySelector('.safe-url').getAttribute('data-url'); el.setAttribute('action',url); }) diff --git a/resources/js/client.js b/resources/js/client.js index cbdbc416..3bfcc485 100644 --- a/resources/js/client.js +++ b/resources/js/client.js @@ -37,3 +37,5 @@ import "../views/segments/login/LoginPatternBg/LoginPatternBg.js"; import "../views/segments/customer/AvisaCustomer/AvisaCustomer.js"; import "../views/segments/attachments_page/DenaAttachList/DenaAttachList.js"; import "../views/segments/attachment/AttachmentWithPreview/AttachmentWithPreview.js"; +import "../views/segments/contact/MeloContact/MeloContact.js"; +import "../views/segments/index/InlineMap/InlineMap.js"; diff --git a/resources/sass/client.scss b/resources/sass/client.scss index ed562ca8..12f4ac85 100644 --- a/resources/sass/client.scss +++ b/resources/sass/client.scss @@ -48,3 +48,5 @@ $xshop-shadow:2px 2px 4px #777777; @import "../views/segments/customer/AvisaCustomer/AvisaCustomer"; @import "../views/segments/attachments_page/DenaAttachList/DenaAttachList"; @import "../views/segments/attachment/AttachmentWithPreview/AttachmentWithPreview"; +@import "../views/segments/contact/MeloContact/MeloContact"; +@import "../views/segments/index/InlineMap/InlineMap"; diff --git a/resources/sass/panel/_fix.scss b/resources/sass/panel/_fix.scss index 58a30d18..eaa6fb79 100644 --- a/resources/sass/panel/_fix.scss +++ b/resources/sass/panel/_fix.scss @@ -46,7 +46,7 @@ main{ } a,a:visited{ - color: #cb00a5; + color: white; &:hover{ color: #ff0067; } diff --git a/resources/views/segments/card/NsCard/NsCard.blade.php b/resources/views/segments/card/NsCard/NsCard.blade.php index 150b5c78..84a2c6e0 100644 --- a/resources/views/segments/card/NsCard/NsCard.blade.php +++ b/resources/views/segments/card/NsCard/NsCard.blade.php @@ -6,7 +6,7 @@ {{__("There is nothing added to card!")}} </div> @else {{-- count 0--}} - <form method="post" class="safe-from" > + <form method="post" class="safe-form" > <input type="hidden" class="safe-url" data-url="{{route('client.card.check')}}"> @csrf diff --git a/resources/views/segments/comments/SimpleComments/SimpleComments.blade.php b/resources/views/segments/comments/SimpleComments/SimpleComments.blade.php index 3ad57d68..c04ea282 100644 --- a/resources/views/segments/comments/SimpleComments/SimpleComments.blade.php +++ b/resources/views/segments/comments/SimpleComments/SimpleComments.blade.php @@ -10,7 +10,7 @@ {{__("Post your comment")}} </h5> @include('components.err') - <form id="comment-form" class="safe-from" method="post"> + <form id="comment-form" class="safe-form" method="post"> <div class="safe-url" data-url="{{route('client.comment.submit')}}"></div> @csrf diff --git a/resources/views/segments/contact/MeloContact/MeloContact.blade.php b/resources/views/segments/contact/MeloContact/MeloContact.blade.php new file mode 100644 index 00000000..a9ce4961 --- /dev/null +++ b/resources/views/segments/contact/MeloContact/MeloContact.blade.php @@ -0,0 +1,129 @@ +<section class='MeloContact'> + <div class="{{gfx()['container']}}"> + + <h1 class="text-center fw-light mb-3"> + {{getSetting($data->area->name.'_'.$data->part.'_title')}} + </h1> + <div class="row"> + <div class="col-md-5"> + <div class="pin-box p-3"> + <i class="ri-mail-add-line icon"></i> + @if(getGroupBySetting($data->area->name.'_'.$data->part)?->posts()->where('status',1)->where('is_pinned',1)->count() == 0) + <h3 class="p-4 text-center"> + {{__("You must add a pinned post to :GROUP",['GROUP' => getGroupBySetting($data->area->name.'_'.$data->part)?->name])}} + </h3> + @else + <h3> + {{getGroupBySetting($data->area->name.'_'.$data->part)?->posts()->where('status',1)->where('is_pinned',1)->first()->title}} + </h3> + {!! getGroupBySetting($data->area->name.'_'.$data->part)?->posts()->where('status',1)->where('is_pinned',1)->first()->body!!} + + <ul class="social text-center"> + @foreach(getSettingsGroup('social_')??[] as $k => $social) + <li class="d-inline-block mx-2"> + <a href="{{$social}}"> + <i class="ri-{{$k}}-line"></i> + </a> + </li> + @endforeach + </ul> + @endif + </div> + </div> + <div class="col-md-7"> + + @include('components.err') + <form class="safe-form" method="post"> + <input type="hidden" class="safe-url" data-url="{{route('client.send-contact')}}"> + @csrf + + <div class="row"> + <div class="col-md-6"> + <div class="form-group"> + <label for="full_name"> + {{__('Name and lastname')}} + </label> + <input name="full_name" type="text" + class="form-control @error('full_name') is-invalid @enderror" + placeholder="{{__('Name and lastname')}}" + value="{{old('full_name',auth('customer')->user()->name??null)}}"/> + </div> + </div> + <div class="col-md-6"> + <div class="form-group"> + <label for="Phone"> + {{__('Phone')}} + </label> + <input name="phone" type="tel" + class="form-control @error('Phone') is-invalid @enderror" + placeholder="{{__('Phone')}}" value="{{old('Phone',auth('customer')->user()->mobile??null)}}"/> + </div> + </div> + <div class="col-md-6 mt-3"> + <div class="form-group"> + <label for="email"> + {{__('Email')}} + </label> + <input name="email" type="email" + class="form-control @error('email') is-invalid @enderror" + placeholder="{{__('Email')}}" value="{{old('email',auth('customer')->user()->email??null)}}"/> + </div> + </div> + <div class="col-md-6 mt-3"> + <div class="form-group"> + <label for="subject"> + {{__('Subject')}} + </label> + <input name="subject" type="text" + class="form-control @error('subject') is-invalid @enderror" + placeholder="{{__('Subject')}}" + value="{{old('subject')}}"/> + </div> + </div> + <div class="col-md-12 mt-3"> + <div class="form-group"> + <label for="body"> + {{__('Your message...')}} + </label> + <textarea name="bodya" style=" height: 150px;" + class="form-control @error('bodya') is-invalid @enderror" + placeholder="{{__('Question/Message')}}">{{old('body')}}</textarea> + </div> + </div> + <div class="col-md-112"> + <label> </label> + <button class="btn btn-primary mt-2 w-100"> + <i class="ri-send-plane-line"></i> + {{__('Send')}} + </button> + </div> + </div> + + </form> + </div> + </div> + <div class="py-5"> + + @php($dir = langIsRTL(app()->getLocale() )?'rtl':'ltr' ) + + @foreach( getGroupBySetting($data->area->name.'_'.$data->part)?->posts()->where('status',1) + ->where('is_pinned',0)->orderByDesc('id')->get() as $i => $post) + <div class="row mb-2" @if( ($i % 2) == 0) dir="rtl" @else dir="ltr" @endif> + <div class="col-md-2"> + <img src="{{$post->imgUrl()}}" alt="{{$post->title}}" class="img-fluid"> + </div> + <div class="col-md" dir="{{$dir}}"> + <h3> + <a href="{{$post->webUrl()}}"> + {{$post->title}} + </a> + </h3> + <p> + {{$post->subtitle}} + </p> + </div> + </div> + @endforeach + </div> + </div> +</section> diff --git a/resources/views/segments/contact/MeloContact/MeloContact.js b/resources/views/segments/contact/MeloContact/MeloContact.js new file mode 100644 index 00000000..e69de29b diff --git a/resources/views/segments/contact/MeloContact/MeloContact.json b/resources/views/segments/contact/MeloContact/MeloContact.json new file mode 100644 index 00000000..325287f8 --- /dev/null +++ b/resources/views/segments/contact/MeloContact/MeloContact.json @@ -0,0 +1,10 @@ +{ + "name": "MeloContact", + "version": "1.0", + "author": "xStack", + "email": "xshop@xstack.ir", + "license": "GPL-3.0-or-later", + "url": "https:\/\/xstack.ir", + "author_url": "https:\/\/4xmen.ir", + "packages": [] +} diff --git a/resources/views/segments/contact/MeloContact/MeloContact.php b/resources/views/segments/contact/MeloContact/MeloContact.php new file mode 100644 index 00000000..ae7ce853 --- /dev/null +++ b/resources/views/segments/contact/MeloContact/MeloContact.php @@ -0,0 +1,42 @@ +<?php + +namespace Resources\Views\Segments; + +use App\Models\Group; +use App\Models\Part; +use App\Models\Setting; + +class MeloContact +{ + public static function onAdd(Part $part = null) + { + $setting = new Setting(); + $setting->section = 'theme'; + $setting->key = $part->area->name . '_' . $part->part; + $setting->value = Group::first()->id; + $setting->type = 'GROUP'; + $setting->size = 6; + $setting->title = $part->area->name . ' ' . $part->part; + $setting->save(); + + $setting = new Setting(); + $setting->section = 'theme'; + $setting->key = $part->area->name . '_' . $part->part.'_title'; + $setting->value = __("Contact us"); + $setting->type = 'TEXT'; + $setting->size = 6; + $setting->title = $part->area->name . ' ' . $part->part . ' title'; + $setting->save(); + } + public static function onRemove(Part $part = null) + { + Setting::where('key',$part->area->name . '_' . $part->part)->first()?->delete(); + Setting::where('key',$part->area->name . '_' . $part->part.'_title')->first()?->delete(); + + + } + public static function onMount(Part $part = null) + { + return $part; + } +} diff --git a/resources/views/segments/contact/MeloContact/MeloContact.scss b/resources/views/segments/contact/MeloContact/MeloContact.scss new file mode 100644 index 00000000..d044ca35 --- /dev/null +++ b/resources/views/segments/contact/MeloContact/MeloContact.scss @@ -0,0 +1,39 @@ +.MeloContact { + padding: 2rem 0; + h1{ + border-bottom: 1px solid var(--xshop-primary); + } + .pin-box{ + background: var(--xshop-secondary); + border-radius: var(--xshop-border-radius); + min-height: 400px; + position: relative; + color: var(--xshop-diff2); + + i.icon{ + position: absolute; + inset-inline-end: -1%; + top: -10%; + font-size:128px; + opacity: .3; + transform: rotateZ(-17deg); + } + + .social{ + position: absolute; + left: 0; + right: 0; + bottom: 0; + + a,a:visited{ + color: var(--xshop-diff2); + + + i{ + font-size: 30px; + } + } + } + } + +} diff --git a/resources/views/segments/contact/MeloContact/screenshot.png b/resources/views/segments/contact/MeloContact/screenshot.png new file mode 100644 index 00000000..4d415873 Binary files /dev/null and b/resources/views/segments/contact/MeloContact/screenshot.png differ diff --git a/resources/views/segments/index/InlineMap/InlineMap.blade.php b/resources/views/segments/index/InlineMap/InlineMap.blade.php index 38a9f78d..9730911c 100644 --- a/resources/views/segments/index/InlineMap/InlineMap.blade.php +++ b/resources/views/segments/index/InlineMap/InlineMap.blade.php @@ -1,4 +1,11 @@ <section id='InlineMap'> + <div class="{{gfx()['container']}}"> + <h5> + <a href="{{getSetting($data->area->name.'_'.$data->part.'_link')}}"> + {{getSetting($data->area->name.'_'.$data->part.'_title')}} + </a> + </h5> + </div> <div id="mapContainer" @if(getSetting($data->area->name.'_'.$data->part.'_dark')) class="dark-mode" @endif> </div> diff --git a/resources/views/segments/index/InlineMap/InlineMap.php b/resources/views/segments/index/InlineMap/InlineMap.php index 6799611a..2caf4172 100644 --- a/resources/views/segments/index/InlineMap/InlineMap.php +++ b/resources/views/segments/index/InlineMap/InlineMap.php @@ -19,11 +19,31 @@ public static function onAdd(Part $part = null) $setting->title = $part->area->name . ' ' . $part->part. ' location'; $setting->save(); + $setting = new Setting(); + $setting->section = 'theme'; + $setting->key = $part->area->name . '_' . $part->part.'_title'; + $setting->value = ''; + $setting->size = 12; + $setting->type = 'TEXT'; +// $setting->data = json_encode(['xmin' => 2, 'xmax' => 90]); + $setting->title = $part->area->name . ' ' . $part->part. ' title'; + $setting->save(); + + $setting = new Setting(); + $setting->section = 'theme'; + $setting->key = $part->area->name . '_' . $part->part.'_link'; + $setting->value = ''; + $setting->size = 6; + $setting->type = 'TEXT'; +// $setting->data = json_encode(['xmin' => 2, 'xmax' => 90]); + $setting->title = $part->area->name . ' ' . $part->part. ' link'; + $setting->save(); + $setting = new Setting(); $setting->section = 'theme'; $setting->key = $part->area->name . '_' . $part->part.'_dark'; $setting->value = 0; - $setting->size = 12; + $setting->size = 6; $setting->type = 'CHECKBOX'; // $setting->data = json_encode(['xmin' => 2, 'xmax' => 90]); $setting->title = $part->area->name . ' ' . $part->part. ' dark mode'; @@ -32,6 +52,8 @@ public static function onAdd(Part $part = null) public static function onRemove(Part $part = null) { Setting::where('key',$part->area->name . '_' . $part->part.'_loc')->first()?->delete(); + Setting::where('key',$part->area->name . '_' . $part->part.'_title')->first()?->delete(); + Setting::where('key',$part->area->name . '_' . $part->part.'_link')->first()?->delete(); Setting::where('key',$part->area->name . '_' . $part->part.'_dark')->first()?->delete(); } public static function onMount(Part $part = null) diff --git a/resources/views/website/inc/website-head.blade.php b/resources/views/website/inc/website-head.blade.php index 9a0952a1..3854bfaa 100644 --- a/resources/views/website/inc/website-head.blade.php +++ b/resources/views/website/inc/website-head.blade.php @@ -1,5 +1,5 @@ <!doctype html> -<html lang="{{config('app.locale')}}" @if(langIsRTL(config('app.locale'))) dir="rtl" @else dir="ltr" @endif @if(gfx()['dark'] == 1) data-bs-theme="dark" @endif > +<html lang="{{app()->getLocale()}}" @if(langIsRTL(app()->getLocale())) dir="rtl" @else dir="ltr" @endif @if(gfx()['dark'] == 1) data-bs-theme="dark" @endif > <head> <meta charset="UTF-8"> <meta name="viewport" diff --git a/routes/web.php b/routes/web.php index e4736778..89337e3d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -372,6 +372,8 @@ function () { Route::get('/customer/check/auth-code', [ClientController::class, 'checkAuth'])->name('check-auth'); Route::get('/customer/profile', [ClientController::class, 'profile'])->name('profile'); Route::get('/compare', [ClientController::class, 'compare'])->name('compare'); + Route::get('/contact-us', [ClientController::class, 'contact'])->name('contact'); + Route::post('/contact-us/submit', [ClientController::class, 'sendContact'])->name('send-contact'); Route::get('/galleries', [ClientController::class, 'galleries'])->name('galleries'); Route::get('/videos', [ClientController::class, 'clips'])->name('clips'); Route::post('/card/check', [\App\Http\Controllers\CardController::class, 'check'])->name('card.check');