added login big bg

added login js
added customer sign-in process
master
A1Gard 2 months ago
parent c6ade855d2
commit 1b2123daac

@ -80,3 +80,6 @@ XLANG_API_URL="http://5.255.98.77:3001"
CURRENCY_SYMBOL="$"
CURRENCY_FACTOR=1
CURRENCY_CODE=USD
SIGN_SMS=true
SIGN_DRIVER=Kavenegar

@ -427,7 +427,7 @@ function showCatNested($cats, $parent = null)
foreach ($cats as $cat) {
if ($cat->parent_id == $parent) {
$ret .= "<li>";
$ret .= "<a href='".$cat->webUrl()."'>";
$ret .= "<a href='" . $cat->webUrl() . "'>";
$ret .= $cat->name . '</a>';
$ret .= showCatNested($cats, $cat->id);
$ret .= "</li>";
@ -849,6 +849,7 @@ function getCategoryProductBySetting($key, $limit = 10, $order = 'id', $dir = "D
return Category::where('id', getSetting($key) ?? 1)->first()
->products()->where('status', 1)->orderBy($order, $dir)->limit($limit)->get();
}
/**
* get group's posts by setting key
* @param $key
@ -936,5 +937,41 @@ function errors($errors, $status = 422, $message = null, $data = null)
*/
function readable($text)
{
return ucfirst(trim(str_replace(['-','_'],' ',$text)));
return ucfirst(trim(str_replace(['-', '_'], ' ', $text)));
}
/**
* register guest logs
* @param $action
* @param $type
* @param $id
* @return void
*/
function guestLog($action, $type = null, $id = null)
{
$gl = new \App\Models\GuestLog();
$gl->action = $action;
$gl->ip = request()->ip();
$gl->loggable_type = $type;
$gl->loggable_id = $id;
$gl->save();
}
/**
* is user try more than allowed or not
* @param $action
* @param $max
* @param $minutes
* @return bool
*/
function isGuestMaxAttemptTry($action, $max = 5, $minutes = 60)
{
if (\App\Models\GuestLog::where('ip', request()->ip())
->where('action', $action)
->where('created_at', '<' ,time() - ($minutes * 60) )->count() >= $max) {
return true;
} else {
return false;
}
}

@ -188,12 +188,12 @@ class ClientController extends Controller
if (isset($request->input('meta')[$prop->name]) && $request->input('meta')[$prop->name] != '' && $request->input('meta')[$prop->name] != '[]') {
switch ($prop->type) {
case 'checkbox':
if ($prop->priceable){
if ($prop->priceable) {
$id = Quantity::where('count', '>', 0)
->where('data', 'LIKE', '%"'.$prop->name.'":%')
->where('data', 'LIKE', '%"' . $prop->name . '":%')
->pluck('product_id')->toArray();
$query->whereIn('id', $id);
}else{
} else {
$query->whereHasMeta($prop->name);
}
@ -201,15 +201,15 @@ class ClientController extends Controller
case 'number':
case 'select':
case 'color':
if ($prop->priceable){
if ($prop->priceable) {
$id = Quantity::where('count', '>', 0)
->where('data', 'LIKE', '%"'.$prop->name.'":"' . $request->meta[$prop->name] . '"%')
->where('data', 'LIKE', '%"' . $prop->name . '":"' . $request->meta[$prop->name] . '"%')
->pluck('product_id')->toArray();
$id = array_merge($id,$query->whereMeta($prop->name, $request->input('meta')[$prop->name])->pluck('id')->toArray());
$id = array_merge($id, $query->whereMeta($prop->name, $request->input('meta')[$prop->name])->pluck('id')->toArray());
$id = array_unique($id);
$query->whereIn('id', $id);
}else{
} else {
$query->whereMeta($prop->name, $request->input('meta')[$prop->name]);
}
break;
@ -218,7 +218,7 @@ class ClientController extends Controller
break;
case 'multi':
case 'singlemulti':
if ($prop->priceable){
if ($prop->priceable) {
$q = Quantity::where('count', '>', 0);
$metas = json_decode($request->meta[$prop->name], true);
$q->where(function ($query) use ($metas) {
@ -226,9 +226,9 @@ class ClientController extends Controller
$query->orWhere('data', 'LIKE', '%' . $meta . '%');
}
});
$query->whereIn('id',$q->pluck('product_id')->toArray());
}else{
$q = Meta::where('key',$prop->name)->where('metable_type',Product::class);
$query->whereIn('id', $q->pluck('product_id')->toArray());
} else {
$q = Meta::where('key', $prop->name)->where('metable_type', Product::class);
$metas = json_decode($request->meta[$prop->name], true);
$q->where(function ($query) use ($metas) {
foreach ($metas as $meta) {
@ -236,7 +236,7 @@ class ClientController extends Controller
}
});
$query->whereIn('id',$q->pluck('metable_id')->toArray());
$query->whereIn('id', $q->pluck('metable_id')->toArray());
}
}
@ -351,15 +351,134 @@ class ClientController extends Controller
}
public function compare()
{
$area = 'compare';
$title = __("Compare products");
$subtitle = '';
$ids = json_decode(\Cookie::get('compares'), true);
$products = Product::whereIn('id',$ids)->where('status',1)->get();
$products = Product::whereIn('id', $ids)->where('status', 1)->get();
return view('client.default-list', compact('area', 'products', 'title', 'subtitle'));
}
public function signOut()
{
auth('customer')->logout();
return redirect()->route('client.sign-in')->with(['message' => __("Signed out successfully")]);
}
public function signIn()
{
$area = 'login';
$title = __("sign in");
$subtitle = 'Sign in as customer';
return view('client.default-list', compact('area', 'title', 'subtitle'));
}
public function signUp()
{
}
public function singInDo(Request $request)
{
$max = 3;
$request->validate([
'email' => 'required|string|email|max:255',
'password' => 'required|string|min:6',
]);
if (isGuestMaxAttemptTry('login', $max)) {
return redirect()->back()->withErrors([__('You try more than :COUNT attempts, Try it later', ["COUNT" => $max])]);
}
guestLog('login');
$customer = Customer::where('email', $request->input('email'));
if ($customer->count() == 0) {
return redirect()->back()->withErrors([__('Email or password is incorrect')]);
}
$customer = $customer->first();
if (\Hash::check($request->input('password'), $customer->password)) {
auth('customer')->login($customer);
return redirect()->route('client.profile')->with(['message' => __('Signed in successfully')]);
} else {
return redirect()->back()->withErrors([__('Email or password is incorrect'), __('If you forget your password call us')]);
}
}
public function profile()
{
return auth('customer')->user();
}
public function sendSms(Request $request)
{
if (isGuestMaxAttemptTry('sms', 1, 2)) {
return [
'OK' => false,
'message' => __('You try attempts, Try it a few minutes'),
'error' => __('You try attempts, Try it a few minutes'),
];
}
guestLog('sms');
$customer = Customer::where('mobile', $request->input('tel'));
$code = rand(11111, 99999);
if ($customer->count() == 0) {
$customer = new Customer();
$customer->mobile = $request->input('tel');
$customer->code = $code;
$customer->save();
} else {
$customer = $customer->first();
$customer->code = $code;
$customer->save();
}
// WIP send sms
return [
'OK' => true,
'message' => __('Auth code send successfully'),
];
}
public function checkAuth(Request $request)
{
$max = 3;
$request->validate([
'tel' => 'required|string|min:6',
'code' => 'required|string|min:5',
]);
if (isGuestMaxAttemptTry('login', $max)) {
return redirect()->back()->withErrors([__('You try more than :COUNT attempts, Try it later', ["COUNT" => $max])]);
}
guestLog('login');
$customer = Customer::where('mobile', $request->input('tel'))
->where('code', $request->input('code'))->first();
if ($customer == null) {
return [
'OK' => false,
'message' => __('Auth code is invalid'),
'error' => __('Auth code is invalid'),
];
}
$customer->code = null;
$customer->save();
auth('customer')->login($customer);
return [
'OK' => true,
'message' => __('You are logged in successfully'),
];
}
}

@ -8,4 +8,6 @@ use Illuminate\Database\Eloquent\Model;
class GuestLog extends Model
{
use HasFactory;
public static $actions = ['login','register','search','sms'];
}

@ -150,6 +150,18 @@ return [
'factor' => env('CURRENCY_FACTOR',1),
'code'=> env('CURRENCY_CODE','USD'),
],
/*
|--------------------------------------------------------------------------
| sign in/up config
|--------------------------------------------------------------------------
|
*/
'sign' => [
'sms' => env('SIGN_SMS',false),
'driver' => env('SIGN_DRIVER',''),
],
/*
|--------------------------------------------------------------------------
| Media

@ -15,7 +15,7 @@ return new class extends Migration
$table->id();
$table->ipAddress('ip');
$table->string('action');
$table->morphs('loggable');
$table->nullableMorphs('loggable');
$table->timestamps();
});
}

@ -0,0 +1,50 @@
import axios from "axios";
function isValidMobile(p) {
const regex = /^(\+|[0-9])([0-9]{9,14})$/gm;
return regex.test(p);
}
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('#send-auth-code')?.addEventListener('click', async function () {
let url = this.getAttribute('data-route');
let tel = document.querySelector('#tel').value;
if (tel.length < 11 || !isValidMobile(tel)){
window.$toast.error('Invalid mobile');
return;
}
let resp = await axios.get(url+'?tel='+tel);
if (resp.data.OK){
window.$toast.success(resp.data.message);
document.querySelector('#tel').setAttribute('readonly','');
document.querySelector('.not-send').style.display = 'block';
document.querySelector('.sent').style.display = 'none';
}else{
window.$toast.error(resp.data.message);
}
});
document.querySelector('#send-auth-check')?.addEventListener('click', async function () {
let url = this.getAttribute('data-route');
let tel = document.querySelector('#tel').value;
let code = document.querySelector('#auth').value;
if (tel.length < 11 || !isValidMobile(tel)){
window.$toast.error('Invalid mobile');
return;
}
if (code.length != 5 ){
window.$toast.error('Invalid code');
return;
}
let resp = await axios.get(url+'?tel='+tel+'&code='+code);
if (resp.data.OK){
window.$toast.success(resp.data.message);
setTimeout( () => {
window.location.href = this.getAttribute('data-profile');
},5000);
}else{
window.$toast.error(resp.data.message);
}
});
});

@ -0,0 +1,54 @@
<section id='LoginBigBg'
style="background-image: url('{{asset('upload/images/'.$data->area->name.'.'.$data->part.'.jpg')}}')">
<form @if(!config('app.sign.sms')) action="{{route('client.sign-in-do')}}" @endif id="login-form" method="post">
@csrf
<h3>
{{$subtitle}}
</h3>
<div class="text-start">
@include('components.err')
</div>
<div id="login-content">
@if(!config('app.sign.sms'))
<label>
{{__("Email")}}
</label>
<input type="email" class="form-control" placeholder="{{__("Email")}}" name="email"
value="{{old('email')}}">
<label class="mt-2">
{{__("Password")}}
</label>
<input type="password" class="form-control" placeholder="{{__('Password')}}" name="password">
<button class="btn btn-outline-primary w-100 mt-3">
{{__("Sign-in")}}
</button>
@else
<label>
{{__("Mobile")}}
</label>
<input type="tel" maxlength="12" class="form-control text-center"
id="tel" placeholder="{{__("09xxxxxxxx")}}">
<div class="not-send">
<label>
{{__("Auth code")}}
</label>
<input type="tel" maxlength="5" minlength="5" id="auth" class="form-control text-center" placeholder="xxxxx">
<button type="button" class="btn btn-outline-primary w-100 mt-3"
id="send-auth-check" data-route="{{route('client.check-auth')}}" data-profile="{{route('client.profile')}}">
{{__("Check authenticate code")}}
</button>
</div>
<div class="sent">
<button type="button" class="btn btn-outline-primary w-100 mt-3"
id="send-auth-code" data-route="{{route('client.send-sms')}}">
{{__("Send authenticate code")}}
</button>
</div>
@endif
</div>
</form>
</section>

@ -0,0 +1,10 @@
{
"name": "LoginBigBg",
"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": []
}

@ -0,0 +1,32 @@
<?php
namespace Resources\Views\Segments;
use App\Models\Part;
use App\Models\Setting;
use Illuminate\Support\Facades\File;
class LoginBigBg
{
public static function onAdd(Part $part = null)
{
$setting = new Setting();
$setting->section = 'theme';
$setting->key = $part->area->name . '_' . $part->part.'_jpg';
$setting->value = null;
$setting->type = 'FILE';
$setting->size = 12;
$setting->title = $part->area->name . ' ' . $part->part.' background image';
$setting->save();
File::copy(__DIR__.'/../../default-assets/bg-girl.jpg',public_path('upload/images/').$part->area->name . '.' . $part->part.'.jpg');
}
public static function onRemove(Part $part = null)
{
}
public static function onMount(Part $part = null)
{
return $part;
}
}

@ -0,0 +1,27 @@
#LoginBigBg {
height: 90vh;
background-size: cover;
background-position: center;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
#login-form{
max-width: 90%;
width: 450px;
}
#login-content{
text-align: start;
padding: 1rem;
background: #ffffff99;
backdrop-filter: blur(4px);
border-radius: var(--xshop-border-radius);
}
.not-send{
display: none;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 KiB

@ -361,6 +361,13 @@ Route::middleware([\App\Http\Middleware\VisitorCounter::class])
// index
Route::get('/', [\App\Http\Controllers\ClientController::class,'welcome'])->name('welcome');
Route::get('/posts', [\App\Http\Controllers\ClientController::class,'posts'])->name('posts');
Route::get('/customer/sign-out', [\App\Http\Controllers\ClientController::class,'signOut'])->name('sign-out');
Route::post('/customer/sign-in/do', [\App\Http\Controllers\ClientController::class,'singInDo'])->name('sign-in-do');
Route::get('/customer/sign-in', [\App\Http\Controllers\ClientController::class,'signIn'])->name('sign-in');
Route::get('/customer/sign-up', [\App\Http\Controllers\ClientController::class,'signUp'])->name('sign-up');
Route::get('/customer/send/auth-code', [\App\Http\Controllers\ClientController::class,'sendSms'])->name('send-sms');
Route::get('/customer/check/auth-code', [\App\Http\Controllers\ClientController::class,'checkAuth'])->name('check-auth');
Route::get('/customer/profile', [\App\Http\Controllers\ClientController::class,'profile'])->name('profile');
Route::get('/compare', [\App\Http\Controllers\ClientController::class,'compare'])->name('compare');
Route::get('/galleries', [\App\Http\Controllers\ClientController::class,'galleries'])->name('galleries');
Route::get('/products', [\App\Http\Controllers\ClientController::class,'products'])->name('products');

Loading…
Cancel
Save