converting login reactjs codes to laravel php using livewire

This commit is contained in:
armiejean 2025-04-11 12:23:31 +08:00
parent deb9afe175
commit 041518c8cb
16 changed files with 1013 additions and 3 deletions

View File

@ -0,0 +1,13 @@
<?php
namespace App\Livewire;
use Livewire\Component;
class ChangePassword extends Component
{
public function render()
{
return view('livewire.change-password');
}
}

157
app/Livewire/Login.php Normal file
View File

@ -0,0 +1,157 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Services\ApiService;
use App\Services\CookieService;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Log;
class Login extends Component
{
public $username = '';
public $password = '';
public $isSubmitting = false;
public $userVerified = false;
public $isModalVisible = false;
public $forgotUsername = false;
public $userEmail = '';
public $userLogo = '';
public $mounted = false;
public $role = null;
public $errors = [];
protected $apiService;
protected $cookieService;
public function boot(ApiService $apiService, CookieService $cookieService)
{
$this->apiService = $apiService;
$this->cookieService = $cookieService;
}
public function mount()
{
if (Session::get('isAuthenticated')) {
return redirect('/my-profile'); // Adjust based on role if needed
}
try {
$contactResponse = $this->apiService->get('systemPreference/contact_details');
$logoResponse = $this->apiService->get('systemPreference/logo');
$this->userEmail = $contactResponse['data']['value'] ?? '';
$this->userLogo = $logoResponse['data']['value'] ?? '';
$this->mounted = true;
} catch (\Exception $e) {
Log::error('Failed to load system preferences', ['error' => $e->getMessage(), 'source' => 'LoginComponent']);
}
}
public function checkUser()
{
$this->isSubmitting = true;
$this->errors = [];
try {
$this->validate([
'username' => ['required', 'regex:/^[A-Za-z0-9_@. ]+$/'],
], [
'username.required' => 'Username is required!',
'username.regex' => 'Invalid username.',
]);
$response = $this->apiService->post('/login_username', ['username' => $this->username]);
$this->userVerified = $response['data']['is_verified'] ?? false;
$this->role = $response['data']['role'] ?? null;
} catch (\Illuminate\Validation\ValidationException $e) {
$this->errors = $e->errors();
} catch (\Exception $e) {
$this->errors['username'] = [$e->getMessage()];
Log::error('Username check failed', ['error' => $e->getMessage(), 'source' => 'LoginComponent']);
} finally {
$this->isSubmitting = false;
}
}
public function login()
{
$this->isSubmitting = true;
$this->errors = [];
try {
$this->validate([
'password' => ['required'],
], [
'password.required' => 'Password is required!',
]);
$response = $this->apiService->post('/login_password', [
'username' => $this->username,
'password' => $this->password,
]);
if (isset($response['data']['prompt_password']) && $response['data']['prompt_password']) {
return redirect()->route('change-password', [
'username' => $this->username,
'admin_uuid' => $response['data']['admin_uuid'],
'password' => $this->password,
]);
}
if (isset($response['data']['token'])) {
$token = $response['data']['token'];
$this->cookieService->setCookie(['token' => $token], 'TOKEN');
Session::put('isAuthenticated', true);
$profileResponse = $this->apiService->post('adminProfile');
$userInfo = $profileResponse['data'];
Session::put('userInfo', $userInfo);
Log::info('Login successful', ['source' => 'LoginComponent']);
return redirect('/my-profile'); // Adjust based on role if needed
}
} catch (\Illuminate\Validation\ValidationException $e) {
$this->errors = $e->errors();
} catch (\Exception $e) {
$this->errors['password'] = [$e->getMessage()];
Log::error('Login failed', ['error' => $e->getMessage(), 'source' => 'LoginComponent']);
} finally {
$this->isSubmitting = false;
}
}
public function showModalForgotUsername()
{
$this->isModalVisible = true;
$this->forgotUsername = true;
}
public function showModalChangePassword()
{
$this->isModalVisible = true;
$this->forgotUsername = false;
}
public function hideModal()
{
$this->isModalVisible = false;
}
public function backToLogin()
{
$this->username = '';
$this->password = '';
$this->userVerified = false;
}
public function render()
{
if (!$this->mounted) {
return null;
}
return view('livewire.login')->layout('layouts.app', ['title' => 'Login Page']);
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Tests\Feature\Livewire;
use Livewire\Livewire;
use Tests\TestCase;
use App\Livewire\Login;
class LoginTest extends TestCase
{
/** @test */
public function it_renders_without_crashing()
{
Livewire::test(Login::class)
->assertSee('Login'); // Check if "Login" text is rendered
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use Jenssegers\Agent\Agent;
class PublicTopErrorPage extends Component
{
public function backHandler()
{
$agent = new Agent();
if ($agent->is('iOS')) {
// Trigger iOS native handler
$this->dispatchBrowserEvent('ios-top-up-failed');
} elseif ($agent->is('Android')) {
// Trigger Android native handler
$this->dispatchBrowserEvent('android-top-up-failed');
}
}
public function render()
{
return view('livewire.public-top-error-page')->layout('layouts.app');
}
}

View File

@ -0,0 +1,90 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Services\ApiService;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Log;
use Jenssegers\Agent\Agent;
class PublicTopSuccessPage extends Component
{
public $loading = false;
public $status = '';
public $userInfo = null;
public $message = '';
public $paymentId = '';
public $token = '';
public $payerId = '';
protected $apiService;
public function boot(ApiService $apiService)
{
$this->apiService = $apiService;
}
public function mount()
{
$this->loading = true;
// Get query parameters from the request
$this->paymentId = request()->query('paymentId');
$this->token = request()->query('token');
$this->payerId = request()->query('PayerID');
$payload = [
'paymentId' => $this->paymentId,
'token' => $this->token,
'PayerID' => $this->payerId,
];
try {
$response = $this->apiService->post('paypalExecute', $payload);
if ($response && isset($response['status']) && $response['status'] === 200) {
$this->status = 200;
$this->userInfo = $response['data'];
Log::info('Top-up success', ['source' => 'PublicTopSuccessPage']);
}
} catch (\Exception $e) {
$this->status = $e->getCode() ?: 500;
$this->message = $e->getMessage();
Log::error('Top-up failed', ['error' => $e->getMessage(), 'source' => 'PublicTopSuccessPage']);
} finally {
$this->loading = false;
}
}
public function backHandler()
{
$agent = new Agent();
if ($agent->is('iOS')) {
// Trigger iOS native handler
$this->dispatchBrowserEvent('ios-top-up-failed');
} elseif ($agent->is('Android')) {
// Trigger Android native handler
$this->dispatchBrowserEvent('android-top-up-failed');
}
}
public function backHandlerSuccess()
{
$agent = new Agent();
if ($agent->is('iOS')) {
// Trigger iOS native handler
$this->dispatchBrowserEvent('ios-top-up-success');
} elseif ($agent->is('Android')) {
// Trigger Android native handler (corrected from Failed to Success)
$this->dispatchBrowserEvent('android-top-up-success');
}
}
public function render()
{
return view('livewire.public-top-success-page')->layout('layouts.app');
}
}

View File

@ -0,0 +1,101 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Services\ApiService;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;
class Registration extends Component
{
public $email = '';
public $password = '';
public $confirm_password = '';
public $first_name = '';
public $middle_name = '';
public $last_name = '';
public $website = '';
public $isSubmitting = false;
public $status = '';
public $errors = [];
public $isRegistered = false;
protected $apiService;
public function boot(ApiService $apiService)
{
$this->apiService = $apiService;
}
public function mount()
{
if (Session::get('isRegistered')) {
return redirect()->route('login');
}
}
public function register()
{
$this->isSubmitting = true;
$this->status = 'loading';
$this->errors = [];
try {
$this->validate([
'email' => ['required', 'email'],
'password' => ['required'],
'confirm_password' => ['required', Rule::in([$this->password])],
'first_name' => ['required'],
'middle_name' => ['required'],
'last_name' => ['required'],
'website' => ['required'],
], [
'email.required' => 'Email is required.',
'email.email' => 'Invalid Email address.',
'password.required' => 'Password is required.',
'confirm_password.required' => 'Confirm password is required.',
'confirm_password.in' => 'Passwords do not match.',
'first_name.required' => 'First name is required.',
'middle_name.required' => 'Middle name is required.',
'last_name.required' => 'Last name is required.',
'website.required' => 'Website is required.',
]);
$data = [
'email' => $this->email,
'password' => $this->password,
'first_name' => $this->first_name,
'middle_name' => $this->middle_name,
'last_name' => $this->last_name,
'website' => $this->website,
];
$response = $this->apiService->post('/register', $data);
if ($response && isset($response['status']) && $response['status'] === 201) {
$this->status = 'success';
$this->isRegistered = true;
Session::put('isRegistered', true);
Session::flash('success', 'Registration successful.');
return redirect()->route('login');
}
} catch (\Illuminate\Validation\ValidationException $e) {
$this->status = 'error';
$this->errors = $e->errors();
Log::error('Registration validation failed', ['errors' => $this->errors, 'source' => 'RegistrationComponent']);
} catch (\Exception $e) {
$this->status = 'error';
Session::flash('error', 'Something went wrong: ' . $e->getMessage());
Log::error('Registration failed', ['error' => $e->getMessage(), 'source' => 'RegistrationComponent']);
} finally {
$this->isSubmitting = false;
}
}
public function render()
{
return view('livewire.registration')->layout('layouts.app');
}
}

View File

@ -8,6 +8,7 @@
"require": {
"php": "^8.2",
"guzzlehttp/guzzle": "^7.9",
"jenssegers/agent": "^2.6",
"laravel/framework": "^11.31",
"laravel/tinker": "^2.9",
"laravel/ui": "^4.6",

199
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "76604e550276fef9afccacf4143ff3aa",
"content-hash": "a76eb60c479c8d60dd14c1dc914f137b",
"packages": [
{
"name": "brick/math",
@ -1054,6 +1054,141 @@
],
"time": "2025-02-03T10:55:03+00:00"
},
{
"name": "jaybizzle/crawler-detect",
"version": "v1.3.4",
"source": {
"type": "git",
"url": "https://github.com/JayBizzle/Crawler-Detect.git",
"reference": "d3b7ff28994e1b0de764ab7412fa269a79634ff3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/d3b7ff28994e1b0de764ab7412fa269a79634ff3",
"reference": "d3b7ff28994e1b0de764ab7412fa269a79634ff3",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8|^5.5|^6.5|^9.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Jaybizzle\\CrawlerDetect\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Beech",
"email": "m@rkbee.ch",
"role": "Developer"
}
],
"description": "CrawlerDetect is a PHP class for detecting bots/crawlers/spiders via the user agent",
"homepage": "https://github.com/JayBizzle/Crawler-Detect/",
"keywords": [
"crawler",
"crawler detect",
"crawler detector",
"crawlerdetect",
"php crawler detect"
],
"support": {
"issues": "https://github.com/JayBizzle/Crawler-Detect/issues",
"source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.3.4"
},
"time": "2025-03-05T23:12:10+00:00"
},
{
"name": "jenssegers/agent",
"version": "v2.6.4",
"source": {
"type": "git",
"url": "https://github.com/jenssegers/agent.git",
"reference": "daa11c43729510b3700bc34d414664966b03bffe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jenssegers/agent/zipball/daa11c43729510b3700bc34d414664966b03bffe",
"reference": "daa11c43729510b3700bc34d414664966b03bffe",
"shasum": ""
},
"require": {
"jaybizzle/crawler-detect": "^1.2",
"mobiledetect/mobiledetectlib": "^2.7.6",
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5.0|^6.0|^7.0"
},
"suggest": {
"illuminate/support": "Required for laravel service providers"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Agent": "Jenssegers\\Agent\\Facades\\Agent"
},
"providers": [
"Jenssegers\\Agent\\AgentServiceProvider"
]
},
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Jenssegers\\Agent\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jens Segers",
"homepage": "https://jenssegers.com"
}
],
"description": "Desktop/mobile user agent parser with support for Laravel, based on Mobiledetect",
"homepage": "https://github.com/jenssegers/agent",
"keywords": [
"Agent",
"browser",
"desktop",
"laravel",
"mobile",
"platform",
"user agent",
"useragent"
],
"support": {
"issues": "https://github.com/jenssegers/agent/issues",
"source": "https://github.com/jenssegers/agent/tree/v2.6.4"
},
"funding": [
{
"url": "https://github.com/jenssegers",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/jenssegers/agent",
"type": "tidelift"
}
],
"time": "2020-06-13T08:05:20+00:00"
},
{
"name": "laravel/framework",
"version": "v11.44.2",
@ -2145,6 +2280,68 @@
],
"time": "2025-03-12T20:24:15+00:00"
},
{
"name": "mobiledetect/mobiledetectlib",
"version": "2.8.45",
"source": {
"type": "git",
"url": "https://github.com/serbanghita/Mobile-Detect.git",
"reference": "96aaebcf4f50d3d2692ab81d2c5132e425bca266"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/96aaebcf4f50d3d2692ab81d2c5132e425bca266",
"reference": "96aaebcf4f50d3d2692ab81d2c5132e425bca266",
"shasum": ""
},
"require": {
"php": ">=5.0.0"
},
"require-dev": {
"phpunit/phpunit": "~4.8.36"
},
"type": "library",
"autoload": {
"psr-0": {
"Detection": "namespaced/"
},
"classmap": [
"Mobile_Detect.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Serban Ghita",
"email": "serbanghita@gmail.com",
"homepage": "http://mobiledetect.net",
"role": "Developer"
}
],
"description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.",
"homepage": "https://github.com/serbanghita/Mobile-Detect",
"keywords": [
"detect mobile devices",
"mobile",
"mobile detect",
"mobile detector",
"php mobile detect"
],
"support": {
"issues": "https://github.com/serbanghita/Mobile-Detect/issues",
"source": "https://github.com/serbanghita/Mobile-Detect/tree/2.8.45"
},
"funding": [
{
"url": "https://github.com/serbanghita",
"type": "github"
}
],
"time": "2023-11-07T21:57:25+00:00"
},
{
"name": "monolog/monolog",
"version": "3.9.0",

View File

@ -1,4 +1,101 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Import Bootstrap */
@import 'bootstrap/dist/css/bootstrap.min.css';
/* General styles */
#root {
height: 100%;
overflow: hidden;
}
/* Custom colors and hover effects */
:root {
--primary-color: #e74610; /* Replace Ant Design's orange */
--hover-bg: rgba(231, 70, 16, 0.1);
}
/* Menu styles (adapt for Bootstrap navbar or custom sidebar) */
.nav-link:hover,
.nav-link.active {
color: var(--primary-color) !important;
}
.nav-item:hover {
background-color: var(--hover-bg) !important;
}
/* Scrollbar styles */
::-webkit-scrollbar {
width: 12px;
background-color: #f5f5f5;
}
::-webkit-scrollbar-track {
border-radius: 10px;
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
background-color: #f5f5f5;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
background-color: #b8bbc9;
}
/* Form and button styles */
.form-control:disabled {
cursor: text !important;
}
.btn-sm {
padding: 0 20px !important;
height: 27px !important;
}
/* Breadcrumb (Bootstrap equivalent) */
.breadcrumb-item a:hover {
color: var(--primary-color) !important;
}
.breadcrumb-item:last-child a {
color: #4d4d4d;
font-weight: 500;
opacity: 0.85;
}
/* Custom terms management (adapt for your UI) */
.terms-management {
position: absolute;
left: -42px;
}
.terms-management-parent {
position: relative;
left: -30px;
}
.terms-management-parent .terms-management {
position: relative;
left: 37px;
border-color: var(--primary-color) !important;
background: var(--primary-color);
width: 100px;
color: #fff;
text-align: right;
}
.terms-management-parent .btn:hover,
.terms-management-parent .btn:focus {
background: var(--primary-color);
color: #fff;
}
/* Responsive design */
@media only screen and (max-width: 480px) {
.app-container {
position: fixed;
width: 100%;
}
}

View File

@ -3,11 +3,16 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<title>Unioil - @yield('title')</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
@if(app()->environment('local'))
<script>
localStorage.setItem('debug', 'awesome-react-app:*');
</script>
@endif
</head>
<body>
<div class="container mt-5">
<div id="root" class="app-container h-100">
@yield('content')
</div>
<script src="{{ asset('js/app.js') }}"></script>

View File

@ -0,0 +1,3 @@
<div>
{{-- Close your eyes. Count to one. That is how long forever feels. --}}
</div>

View File

@ -0,0 +1,75 @@
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-6">
<div class="text-center mt-5 mb-4">
<img src="{{ asset('images/logo_unioil.png') }}" alt="Unioil Logo" style="max-width: 200px;">
</div>
<div class="mb-3">
<h1 class="mb-0">Welcome</h1>
@if(!$userVerified)
<span style="font-size: 12px;">Sign in to continue</span>
@endif
</div>
<form wire:submit.prevent="{{ $userVerified ? 'login' : 'checkUser' }}">
<div class="mb-3 position-relative">
@if(!$userVerified)
<label class="form-label fw-medium" style="color: #005598;">Enter Username</label>
<input type="text" class="form-control @error('username') is-invalid @enderror" wire:model="username" placeholder="User name" readonly="{{ $userVerified ? 'true' : 'false' }}">
@error('username') <div class="invalid-feedback">{{ $message }}</div> @enderror
@else
<div class="d-flex align-items-center bg-light border rounded p-2 mb-3" style="border-color: #d9d9d9;">
<span class="input-group-text bg-transparent border-0"><i class="bi bi-person"></i></span>
<span class="flex-grow-1 text-muted">{{ $username }}</span>
<button type="button" wire:click="backToLogin" class="btn btn-link p-0 text-muted"><i class="bi bi-x"></i></button>
</div>
@endif
</div>
@if($userVerified)
<div class="mb-3">
<label class="form-label fw-medium" style="color: #005598;">Enter Password</label>
<input type="password" class="form-control @error('password') is-invalid @enderror" wire:model="password" placeholder="Password">
@error('password') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
@endif
<div class="row mt-4">
<div class="col-6">
@if($userVerified)
<a href="#" wire:click="showModalChangePassword" style="color: #005598;">Forgot Password</a>
@else
<a href="#" wire:click="showModalForgotUsername" style="color: #005598;">Forgot Username</a>
@endif
</div>
<div class="col-6 text-end">
<button type="submit" class="btn btn-primary w-100" wire:loading.attr="disabled" wire:target="{{ $userVerified ? 'login' : 'checkUser' }}" style="background-color: {{ $userVerified ? ($password ? '#E74610' : '#FCFCFC') : ($username ? '#E74610' : '#FCFCFC') }}; border-color: {{ $userVerified ? ($password ? '#E74610' : '#D9D9D9') : ($username ? '#E74610' : '#D9D9D9') }};" {{ $userVerified ? ($password ? '' : 'disabled') : ($username ? '' : 'disabled') }}>
<span wire:loading wire:target="{{ $userVerified ? 'login' : 'checkUser' }}">Processing...</span>
<span wire:loading.remove wire:target="{{ $userVerified ? 'login' : 'checkUser' }}">Next</span>
</button>
</div>
</div>
</form>
<!-- Modal -->
@if($isModalVisible)
<div class="modal fade show d-block" tabindex="-1" style="background-color: rgba(0,0,0,0.5);">
<div class="modal-dialog modal-dialog-centered" style="max-width: 337px;">
<div class="modal-content">
<div class="modal-body">
<h4>Forgot {{ $forgotUsername ? 'Username' : 'Password' }}</h4>
<p>
To have your {{ $forgotUsername ? 'username' : 'password' }} reset, please contact <br>
Unioil's admin at <a href="mailto:{{ $userEmail }}" style="color: #005598;">{{ $userEmail }}</a>
</p>
</div>
<div class="modal-footer justify-content-end">
<button wire:click="hideModal" class="btn btn-primary" style="background-color: #E74610; border-color: #E74610; width: 64px;">Ok</button>
</div>
</div>
</div>
</div>
@endif
</div>
</div>
</div>

View File

@ -0,0 +1,29 @@
<div class="container position-relative" style="min-height: 100vh;">
<div class="text-center position-absolute top-0 start-50 translate-middle-x mt-4">
<img src="{{ asset('images/ic_error.svg') }}" alt="Error" style="width: 24vmin;">
<p class="mt-3" style="line-height: 7vmin; font-size: 6vmin; font-weight: bold; color: #4D4D4D;">
Transaction Failed.<br>
Your purchase for top-up is not <br>successful. Please try again.
</p>
</div>
<div class="position-absolute bottom-0 start-50 translate-middle-x mb-4" style="width: 100%; max-width: 300px;">
<button wire:click="backHandler" class="btn btn-primary w-100" style="height: 11vmin; font-size: 5vmin; background-color: #e74610; border-color: #e74610;">
Return to Top-Up Page
</button>
</div>
<!-- JavaScript for native app integration -->
<script>
window.addEventListener('ios-top-up-failed', function () {
if (typeof window.iOStopUpFailed === 'function') {
window.iOStopUpFailed();
}
});
window.addEventListener('android-top-up-failed', function () {
if (typeof window.AndroidTopUpFailed === 'function') {
window.AndroidTopUpFailed();
}
});
</script>
</div>

View File

@ -0,0 +1,86 @@
<div class="container position-relative" style="min-height: 100vh;">
@if($loading)
<div class="text-center position-absolute top-50 start-50 translate-middle" style="font-size: 6vmin;">
<div class="spinner-border text-primary" role="status"></div>
<span class="ms-2">Loading Top-Up Please wait...</span>
</div>
@else
<div class="mt-5">
@if($status == 200)
<div class="text-center position-absolute top-0 start-50 translate-middle-x mt-4">
<img src="{{ asset('images/ic_success.svg') }}" alt="Success" style="width: 18vmin;">
<p class="mt-3" style="line-height: 7vmin; font-size: 6vmin; font-weight: bold;">
Your purchase for top-up points <br> is successful!
</p>
<div style="font-size: 15px; font-weight: 400;">
<div class="row">
<div class="col-12">
<span style="font-size: 6vmin; font-weight: bold;">{{ $userInfo['date'] ?? '' }}</span>
</div>
<div class="col-12">Card Number: {{ $userInfo['card_number'] ?? '' }}</div>
<div class="col-12">Sales Invoice Number: {{ $userInfo['invoice'] ?? '' }}</div>
</div>
<div class="mt-3" style="font-size: 3.5vmin;">
<div class="row justify-content-between">
<div class="col-6 text-start">Top-up Points Value</div>
<div class="col-6 text-end">{{ $userInfo['points'] ?? '' }}</div>
</div>
<div class="row justify-content-between">
<div class="col-6 text-start">Payment Value</div>
<div class="col-6 text-end">Php {{ $userInfo['payment_val'] ?? '' }}</div>
</div>
<div class="row justify-content-between">
<div class="col-6 text-start">Paypal Fee</div>
<div class="col-6 text-end">Php {{ $userInfo['paypal_fee'] ?? '' }}</div>
</div>
</div>
</div>
</div>
<div class="position-absolute bottom-0 start-50 translate-middle-x mb-4" style="width: 100%; max-width: 300px;">
<button wire:click="backHandlerSuccess" class="btn btn-primary w-100" style="height: 11vmin; font-size: 5vmin; background-color: #e74610; border-color: #e74610;">
Return to Home Page
</button>
</div>
@else
<div class="text-center position-absolute top-0 start-50 translate-middle-x mt-4">
<img src="{{ asset('images/ic_error.svg') }}" alt="Error" style="width: 24vmin;">
<p class="mt-3" style="line-height: 7vmin; font-size: 5vmin; font-weight: bold; color: #4D4D4D;">
Transaction Failed.<br>{{ $message }}
</p>
</div>
<div class="position-absolute bottom-0 start-50 translate-middle-x mb-4" style="width: 100%; max-width: 300px;">
<button wire:click="backHandler" class="btn btn-primary w-100" style="height: 11vmin; font-size: 5vmin; background-color: #e74610; border-color: #e74610;">
Return to Top-Up Page
</button>
</div>
@endif
</div>
@endif
<!-- JavaScript for native app integration -->
<script>
window.addEventListener('ios-top-up-success', function () {
if (typeof window.iOStopUpSuccess === 'function') {
window.iOStopUpSuccess();
}
});
window.addEventListener('ios-top-up-failed', function () {
if (typeof window.iOStopUpFailed === 'function') {
window.iOStopUpFailed();
}
});
window.addEventListener('android-top-up-success', function () {
if (typeof window.AndroidTopUpSuccess === 'function') {
window.AndroidTopUpSuccess();
}
});
window.addEventListener('android-top-up-failed', function () {
if (typeof window.AndroidTopUpFailed === 'function') {
window.AndroidTopUpFailed();
}
});
</script>
</div>

View File

@ -0,0 +1,106 @@
<div class="row justify-content-center align-items-center">
<div class="col-12 col-sm-12 col-lg-6 col-xl-6">
<h1 class="text-center">Registration</h1>
@if($status === 'error' && session('error'))
<div class="alert alert-danger mb-3" role="alert">
{{ session('error') }}
</div>
@endif
<form wire:submit.prevent="register">
<div class="mb-3 row">
<label for="email" class="col-sm-4 col-form-label">E-mail</label>
<div class="col-sm-8">
<input type="email" class="form-control @error('email') is-invalid @enderror" wire:model="email" id="email">
@error('email') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3 row">
<label for="password" class="col-sm-4 col-form-label">Password</label>
<div class="col-sm-8">
<input type="password" class="form-control @error('password') is-invalid @enderror" wire:model="password" id="password">
@error('password') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3 row">
<label for="confirm_password" class="col-sm-4 col-form-label">Confirm Password</label>
<div class="col-sm-8">
<input type="password" class="form-control @error('confirm_password') is-invalid @enderror" wire:model="confirm_password" id="confirm_password">
@error('confirm_password') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3 row">
<label for="first_name" class="col-sm-4 col-form-label">First Name</label>
<div class="col-sm-8">
<input type="text" class="form-control @error('first_name') is-invalid @enderror" wire:model="first_name" id="first_name">
@error('first_name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3 row">
<label for="middle_name" class="col-sm-4 col-form-label">Middle Name</label>
<div class="col-sm-8">
<input type="text" class="form-control @error('middle_name') is-invalid @enderror" wire:model="middle_name" id="middle_name">
@error('middle_name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3 row">
<label for="last_name" class="col-sm-4 col-form-label">Last Name</label>
<div class="col-sm-8">
<input type="text" class="form-control @error('last_name') is-invalid @enderror" wire:model="last_name" id="last_name">
@error('last_name') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3 row">
<label for="website" class="col-sm-4 col-form-label">Website</label>
<div class="col-sm-8">
<select class="form-select @error('website') is-invalid @enderror" wire:model="website" id="website">
<option value="">Select Website</option>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
@error('website') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary" wire:loading.attr="disabled" wire:target="register">
<span wire:loading wire:target="register">Registering...</span>
<span wire:loading.remove wire:target="register">Register</span>
</button>
</div>
</form>
<div class="text-center mt-3">
Back to <a href="{{ route('login') }}">Login</a>
</div>
</div>
</div>
@if(session('success'))
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
Swal.fire({
icon: 'success',
title: 'Success',
text: '{{ session('success') }}',
});
</script>
@endif
@if(session('error'))
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
Swal.fire({
icon: 'error',
title: 'Error',
text: '{{ session('error') }}',
});
</script>
@endif

View File

@ -47,6 +47,12 @@ use App\Livewire\FetchData;
use App\Livewire\Logout;
use App\Livewire\ErrorHandler;
Route::get('/registration', \App\Livewire\Registration::class)->name('registration');
Route::get('/topup-success-page', \App\Livewire\PublicTopSuccessPage::class)->name('topup-success');
Route::get('/topup-error-page', \App\Livewire\PublicTopErrorPage::class)->name('topup-error');
Route::get('/login', \App\Livewire\Login::class)->name('login');
Route::get('/change-password', \App\Livewire\ChangePassword::class)->name('change-password');
Route::get('/fetch-data/{url}', FetchData::class)->name('fetch.data');