update sometimes
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
name: Deploy to Production (Minified)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Deploy to production server
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: ${{ secrets.PROD_HOST }}
|
||||
username: ${{ secrets.PROD_USERNAME }}
|
||||
key: ${{ secrets.PROD_SSH_KEY }}
|
||||
port: ${{ secrets.PROD_PORT || 22 }}
|
||||
script: |
|
||||
# Navigate to project directory
|
||||
cd ${{ secrets.PROD_PROJECT_PATH || '/var/www/portal' }}
|
||||
|
||||
# Backup current deployment
|
||||
echo "💾 Creating backup..."
|
||||
cp -r . ../portal-backup-$(date +%Y%m%d_%H%M%S) || true
|
||||
|
||||
# Pull latest code
|
||||
echo "🔄 Pulling latest code..."
|
||||
git pull origin ${{ github.ref_name }}
|
||||
|
||||
# Install/Update Composer dependencies for production
|
||||
echo "📦 Installing Composer dependencies..."
|
||||
composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# Install/Update NPM dependencies
|
||||
echo "📦 Installing NPM dependencies..."
|
||||
npm ci --only=production
|
||||
|
||||
# Build and minify assets
|
||||
echo "🏗️ Building and minifying assets..."
|
||||
npm run minify-all
|
||||
|
||||
# Run database migrations (if needed)
|
||||
echo "🗃️ Running database migrations..."
|
||||
php artisan migrate --force
|
||||
|
||||
# Laravel optimizations for production
|
||||
echo "⚡ Optimizing Laravel for production..."
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
php artisan optimize
|
||||
|
||||
# Clear all caches
|
||||
echo "🧹 Clearing caches..."
|
||||
php artisan cache:clear
|
||||
php artisan view:clear
|
||||
php artisan config:clear
|
||||
|
||||
# Queue restart (if using queues)
|
||||
echo "🔄 Restarting queues..."
|
||||
php artisan queue:restart || true
|
||||
|
||||
# Set proper permissions
|
||||
echo "🔐 Setting permissions..."
|
||||
chmod -R 755 storage bootstrap/cache public/uploads
|
||||
chown -R www-data:www-data storage bootstrap/cache public/uploads
|
||||
|
||||
# Cleanup old backups (keep last 5)
|
||||
echo "🧹 Cleaning up old backups..."
|
||||
find ../portal-backup-* -maxdepth 0 -type d | sort | head -n -5 | xargs rm -rf || true
|
||||
|
||||
echo "✅ Production deployment completed successfully!"
|
||||
@@ -38,10 +38,14 @@ class OsVersion extends Controller
|
||||
}
|
||||
public function store(OsVersionRequest $request)
|
||||
{
|
||||
$request->validated();
|
||||
$validatedData = $request->validated();
|
||||
|
||||
// Remove unnecessary fields
|
||||
unset($validatedData['vcenter_id'], $validatedData['module_datacenter_id']);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$this->osRepository->create($request->all());
|
||||
$this->osRepository->create($validatedData);
|
||||
DB::commit();
|
||||
} catch (\Exception $error) {
|
||||
DB::rollBack();
|
||||
@@ -69,9 +73,15 @@ class OsVersion extends Controller
|
||||
if (! $version) {
|
||||
return back()->withErrors('Can\'t find version os by ID #' . $id);
|
||||
}
|
||||
|
||||
$validatedData = $request->validated();
|
||||
|
||||
// Remove unnecessary fields
|
||||
unset($validatedData['vcenter_id'], $validatedData['module_datacenter_id']);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$this->osRepository->update($id,$request->all());
|
||||
$this->osRepository->update($id, $validatedData);
|
||||
DB::commit();
|
||||
} catch (\Exception $error) {
|
||||
DB::rollBack();
|
||||
|
||||
@@ -37,6 +37,8 @@ class RechargeController extends Controller
|
||||
|
||||
public function paymentProcess(RechargeRequest $request)
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
$auth = customer();
|
||||
if (!$auth) {
|
||||
return redirect()->route('auth.index')->withErrors('Vui lòng đăng nhập');
|
||||
@@ -44,7 +46,7 @@ class RechargeController extends Controller
|
||||
|
||||
// Chuẩn bị dữ liệu cho VNPAY
|
||||
$paymentData = [
|
||||
'amount' => $request->money,
|
||||
'amount' => $data['total_amount'],
|
||||
'language' => 'vn',
|
||||
];
|
||||
$paymentUrl = $this->vnpayService->createPaymentUrl($paymentData);
|
||||
|
||||
@@ -26,6 +26,7 @@ class OsVersionRequest extends FormRequest
|
||||
'module_host_id' => 'required',
|
||||
'os_group_id' => 'required',
|
||||
'os_id' => 'required',
|
||||
'template_id' => 'nullable',
|
||||
'status' => 'required'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class RechargeRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'money' => 'required|numeric|min:200000',
|
||||
'total_amount' => 'required|numeric|min:200000',
|
||||
'bankCode' => 'nullable|string',
|
||||
];
|
||||
}
|
||||
@@ -31,9 +31,9 @@ class RechargeRequest extends FormRequest
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'money.required' => 'Vui lòng nhập số tiền cần nạp.',
|
||||
'money.numeric' => 'Số tiền phải là một số.',
|
||||
'money.min' => 'Số tiền nạp vui lòng lớn hơn hoặc bằng 200.000vnđ',
|
||||
'total_amount.required' => 'Vui lòng nhập số tiền cần nạp.',
|
||||
'total_amount.numeric' => 'Số tiền phải là một số.',
|
||||
'total_amount.min' => 'Số tiền nạp vui lòng lớn hơn hoặc bằng 200.000vnđ',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,9 +503,6 @@
|
||||
.inset-x-0 {
|
||||
inset-inline: calc(var(--spacing) * 0);
|
||||
}
|
||||
.inset-x-3 {
|
||||
inset-inline: calc(var(--spacing) * 3);
|
||||
}
|
||||
.inset-y-0 {
|
||||
inset-block: calc(var(--spacing) * 0);
|
||||
}
|
||||
@@ -530,9 +527,6 @@
|
||||
.-top-0\.5 {
|
||||
top: calc(var(--spacing) * -0.5);
|
||||
}
|
||||
.-top-1 {
|
||||
top: calc(var(--spacing) * -1);
|
||||
}
|
||||
.-top-10 {
|
||||
top: calc(var(--spacing) * -10);
|
||||
}
|
||||
@@ -608,9 +602,6 @@
|
||||
.-left-0\.5 {
|
||||
left: calc(var(--spacing) * -0.5);
|
||||
}
|
||||
.-left-1 {
|
||||
left: calc(var(--spacing) * -1);
|
||||
}
|
||||
.-left-\[200\%\] {
|
||||
left: calc(200% * -1);
|
||||
}
|
||||
@@ -632,9 +623,6 @@
|
||||
.left-10 {
|
||||
left: calc(var(--spacing) * 10);
|
||||
}
|
||||
.left-full {
|
||||
left: 100%;
|
||||
}
|
||||
.isolate {
|
||||
isolation: isolate;
|
||||
}
|
||||
@@ -920,9 +908,6 @@
|
||||
.mt-\[2px\] {
|
||||
margin-top: 2px;
|
||||
}
|
||||
.mt-\[4\.7rem\] {
|
||||
margin-top: 4.7rem;
|
||||
}
|
||||
.mt-auto {
|
||||
margin-top: auto;
|
||||
}
|
||||
@@ -5518,13 +5503,6 @@
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.group-hover\:visible {
|
||||
&:is(:where(.group):hover *) {
|
||||
@media (hover: hover) {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-hover\:block {
|
||||
&:is(:where(.group):hover *) {
|
||||
@media (hover: hover) {
|
||||
@@ -5556,20 +5534,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-hover\:rotate-180 {
|
||||
&:is(:where(.group):hover *) {
|
||||
@media (hover: hover) {
|
||||
rotate: 180deg;
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-hover\:bg-orange-50 {
|
||||
&:is(:where(.group):hover *) {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-orange-50);
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-hover\:text-gray-500 {
|
||||
&:is(:where(.group):hover *) {
|
||||
@media (hover: hover) {
|
||||
@@ -5598,27 +5562,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-hover\/submenu\:visible {
|
||||
&:is(:where(.group\/submenu):hover *) {
|
||||
@media (hover: hover) {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-hover\/submenu\:rotate-90 {
|
||||
&:is(:where(.group\/submenu):hover *) {
|
||||
@media (hover: hover) {
|
||||
rotate: 90deg;
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-hover\/submenu\:opacity-100 {
|
||||
&:is(:where(.group\/submenu):hover *) {
|
||||
@media (hover: hover) {
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-focus\:hidden {
|
||||
&:is(:where(.group):focus *) {
|
||||
display: none;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg fill="#000000" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="800px" height="800px" viewBox="0 0 92 92" enable-background="new 0 0 92 92" xml:space="preserve">
|
||||
<path id="XMLID_1594_" d="M72.8,24.9L53.4,66.7c-1.7,4.3-4.7,6.8-8,6.8c-2.7,0-5-1.4-6.3-3.6c-1.4-2.6-1.3-5.8,0.4-8.5v0l25.4-40.7
|
||||
c1.3-2,3.9-2.7,6-1.6C73,20.2,73.8,22.7,72.8,24.9z M79.6,37c-1.5-1.6-4-1.7-5.7-0.2c-1.6,1.5-1.7,4-0.2,5.7
|
||||
C80.3,49.7,84,59.1,84,69c0,2.2,1.8,4,4,4s4-1.8,4-4C92,57.1,87.6,45.7,79.6,37z M49.2,30.4c2.2,0.2,4.1-1.4,4.3-3.6
|
||||
c0.2-2.2-1.4-4.1-3.6-4.3c-1.3-0.1-2.6-0.2-3.9-0.2c-25.4,0-46,21-46,46.8c0,2.2,1.8,4,4,4s4-1.8,4-4c0-21.4,17-38.8,38-38.8
|
||||
C47.1,30.2,48.2,30.3,49.2,30.4z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 865 B |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 8C15.1046 8 16 8.89543 16 10V14C16 15.1046 15.1046 16 14 16H10C8.89543 16 8 15.1046 8 14V10C8 8.89543 8.89543 8 10 8H14ZM13 10C13.5523 10 14 10.4477 14 11V13C14 13.5523 13.5523 14 13 14H11C10.4477 14 10 13.5523 10 13V11C10 10.4477 10.4477 10 11 10H13Z" fill="#0F0F0F"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 2C11 1.44772 11.4477 1 12 1C12.5523 1 13 1.44772 13 2V4H15V2C15 1.44772 15.4477 1 16 1C16.5523 1 17 1.44772 17 2V4C18.6569 4 20 5.34315 20 7H22C22.5523 7 23 7.44771 23 8C23 8.55229 22.5523 9 22 9H20V11H22C22.5523 11 23 11.4477 23 12C23 12.5523 22.5523 13 22 13H20V15H22C22.5523 15 23 15.4477 23 16C23 16.5523 22.5523 17 22 17H20C20 18.6569 18.6569 20 17 20V22C17 22.5523 16.5523 23 16 23C15.4477 23 15 22.5523 15 22V20H13V22C13 22.5523 12.5523 23 12 23C11.4477 23 11 22.5523 11 22V20H9V22C9 22.5523 8.55229 23 8 23C7.44771 23 7 22.5523 7 22V20C5.34315 20 4 18.6569 4 17H2C1.44772 17 1 16.5523 1 16C1 15.4477 1.44772 15 2 15H4V13H2C1.44772 13 1 12.5523 1 12C1 11.4477 1.44772 11 2 11H4V9H2C1.44772 9 1 8.55229 1 8C1 7.44771 1.44772 7 2 7H4C4 5.34315 5.34315 4 7 4V2C7 1.44772 7.44771 1 8 1C8.55229 1 9 1.44772 9 2V4H11V2ZM17 6C17.5523 6 18 6.44772 18 7V17C18 17.5523 17.5523 18 17 18H7C6.44771 18 6 17.5523 6 17V7C6 6.44771 6.44772 6 7 6H17Z" fill="#0F0F0F"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 299.92 299.92" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M293.4,65.2H6.52C2.914,65.2,0,68.114,0,71.72v117.36c0,3.606,2.914,6.52,6.52,6.52h6.52v32.6
|
||||
c0,3.606,2.914,6.52,6.52,6.52h260.8c3.606,0,6.52-2.914,6.52-6.52v-32.6h6.52c3.606,0,6.52-2.914,6.52-6.52V71.72
|
||||
C299.92,68.114,297.006,65.2,293.4,65.2z M273.84,221.68h-19.56H228.2h-26.08h-26.08h-26.08h-26.08H97.8H71.72H45.64H26.08V195.6
|
||||
h19.56h26.08H97.8h26.08h26.08h26.08h26.08h26.08h26.08h19.56V221.68z M286.88,182.56h-6.52H19.56h-6.52V78.24h273.84V182.56z"/>
|
||||
<path d="M32.6,169.52h39.12c3.606,0,6.52-2.914,6.52-6.52V97.8c0-3.606-2.914-6.52-6.52-6.52H32.6c-3.606,0-6.52,2.914-6.52,6.52
|
||||
V163C26.08,166.606,28.994,169.52,32.6,169.52z M39.12,104.32H65.2v52.16H39.12V104.32z"/>
|
||||
<path d="M97.8,169.52h39.12c3.606,0,6.52-2.914,6.52-6.52V97.8c0-3.606-2.914-6.52-6.52-6.52H97.8c-3.606,0-6.52,2.914-6.52,6.52
|
||||
V163C91.28,166.606,94.194,169.52,97.8,169.52z M104.32,104.32h26.08v52.16h-26.08V104.32z"/>
|
||||
<path d="M163,169.52h39.12c3.606,0,6.52-2.914,6.52-6.52V97.8c0-3.606-2.914-6.52-6.52-6.52H163c-3.606,0-6.52,2.914-6.52,6.52
|
||||
V163C156.48,166.606,159.394,169.52,163,169.52z M169.52,104.32h26.08v52.16h-26.08V104.32z"/>
|
||||
<path d="M228.2,169.52h39.12c3.606,0,6.52-2.914,6.52-6.52V97.8c0-3.606-2.914-6.52-6.52-6.52H228.2
|
||||
c-3.606,0-6.52,2.914-6.52,6.52V163C221.68,166.606,224.594,169.52,228.2,169.52z M234.72,104.32h26.08v52.16h-26.08V104.32z"/>
|
||||
<path d="M52.16,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52c-3.606,0-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
C49.246,221.68,52.16,218.766,52.16,215.16z"/>
|
||||
<path d="M78.24,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52c-3.606,0-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
C75.326,221.68,78.24,218.766,78.24,215.16z"/>
|
||||
<path d="M104.32,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52c-3.606,0-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
C101.406,221.68,104.32,218.766,104.32,215.16z"/>
|
||||
<path d="M130.4,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52c-3.606,0-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
C127.486,221.68,130.4,218.766,130.4,215.16z"/>
|
||||
<path d="M156.48,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52s-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
S156.48,218.766,156.48,215.16z"/>
|
||||
<path d="M182.56,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52c-3.606,0-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
C179.646,221.68,182.56,218.766,182.56,215.16z"/>
|
||||
<path d="M208.64,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52c-3.606,0-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
C205.726,221.68,208.64,218.766,208.64,215.16z"/>
|
||||
<path d="M234.72,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52c-3.606,0-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
C231.806,221.68,234.72,218.766,234.72,215.16z"/>
|
||||
<path d="M260.8,215.16v-13.04c0-3.606-2.914-6.52-6.52-6.52c-3.606,0-6.52,2.914-6.52,6.52v13.04c0,3.606,2.914,6.52,6.52,6.52
|
||||
C257.886,221.68,260.8,218.766,260.8,215.16z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="#000000" stroke-width="2" d="M2,5.07692308 C2,5.07692308 3.66666667,2 12,2 C20.3333333,2 22,5.07692308 22,5.07692308 L22,18.9230769 C22,18.9230769 20.3333333,22 12,22 C3.66666667,22 2,18.9230769 2,18.9230769 L2,5.07692308 Z M2,13 C2,13 5.33333333,16 12,16 C18.6666667,16 22,13 22,13 M2,7 C2,7 5.33333333,10 12,10 C18.6666667,10 22,7 22,7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 584 B |
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 512 512" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M480.003,128H48c0-22.056-17.944-40-40-40c-4.418,0-8,3.582-8,8s3.582,8,8,8c13.234,0,24,10.766,24,24v288
|
||||
c0,4.418,3.582,8,8,8s8-3.582,8-8v-8h16.01C77.238,408,88,397.238,88,384.01V384h392.003C497.646,384,512,369.646,512,352.003
|
||||
V159.997C512,142.354,497.646,128,480.003,128z M496,352.003c0,8.821-7.176,15.997-15.997,15.997H80c-4.418,0-8,3.582-8,8v8.01
|
||||
c0,4.406-3.584,7.99-7.99,7.99H48V144h432.003c8.821,0,15.997,7.176,15.997,15.997V352.003z"/>
|
||||
<path d="M240,192c-22.922,0-43.057,12.12-54.363,30.28c-0.784,0.849-1.379,1.856-1.737,2.954c-5.03,9.136-7.9,19.621-7.9,30.766
|
||||
c0,11.406,3.013,22.115,8.264,31.399c0.187,0.398,0.407,0.778,0.656,1.14C196.078,307.354,216.586,320,240,320
|
||||
c35.29,0,64-28.71,64-64c0-11.406-3.013-22.115-8.264-31.399c-0.187-0.398-0.407-0.778-0.656-1.14
|
||||
C283.922,204.646,263.414,192,240,192z M192,256c0-4.395,0.605-8.648,1.717-12.695c3.596,3.178,8.453,6.73,15.035,10.53
|
||||
c6.376,3.681,11.742,6.078,16.208,7.612c-2.622,2.061-5.987,4.385-10.208,6.821c-8.449,4.878-14.816,7.039-18.36,7.752
|
||||
C193.58,269.922,192,263.144,192,256z M288,256c0,4.103-0.52,8.087-1.493,11.891c-3.617-3.227-8.542-6.848-15.259-10.726
|
||||
c-5.96-3.441-11.036-5.758-15.321-7.298c2.483-1.885,5.564-3.966,9.321-6.135c8.447-4.876,14.816-7.039,18.36-7.752
|
||||
C286.42,242.078,288,248.856,288,256z M273.948,222.099c-4.562,1.524-10.087,3.96-16.699,7.777
|
||||
c-6.252,3.61-10.952,6.997-14.49,10.051C242.31,236.682,242,232.717,242,228c0-9.763,1.314-16.361,2.469-19.785
|
||||
C255.934,209.279,266.244,214.384,273.948,222.099z M227.619,209.627C226.655,214.344,226,220.354,226,228
|
||||
c0,7.056,0.557,12.721,1.401,17.26c-3.022-1.232-6.59-2.938-10.65-5.282c-8.302-4.793-13.33-9.159-15.769-11.883
|
||||
C207.376,219.18,216.739,212.535,227.619,209.627z M206.049,289.898c4.564-1.524,10.086-3.954,16.702-7.774
|
||||
c6.252-3.61,10.952-6.997,14.49-10.051C237.69,275.318,238,279.283,238,284c0,9.763-1.314,16.361-2.469,19.785
|
||||
C224.065,302.721,213.753,297.615,206.049,289.898z M252.381,302.373C253.345,297.656,254,291.646,254,284
|
||||
c0-7.633-0.653-13.635-1.614-18.347c3.066,1.237,6.708,2.97,10.863,5.368c8.764,5.06,13.892,9.652,16.163,12.33
|
||||
C273.012,292.546,263.486,299.405,252.381,302.373z"/>
|
||||
<path d="M440,168c-4.418,0-8,3.582-8,8s3.582,8,8,8c8.822,0,16,7.178,16,16v112c0,8.822-7.178,16-16,16H240
|
||||
c-39.701,0-72-32.299-72-72s32.299-72,72-72h168c4.418,0,8-3.582,8-8s-3.582-8-8-8H240c-48.523,0-88,39.477-88,88s39.477,88,88,88
|
||||
h200c17.645,0,32-14.355,32-32V200C472,182.355,457.645,168,440,168z"/>
|
||||
<path d="M112,232H88c-8.822,0-16,7.178-16,16v16c0,8.822,7.178,16,16,16h24c8.822,0,16-7.178,16-16v-16
|
||||
C128,239.178,120.822,232,112,232z M88,264v-16h24l0.001,16H88z"/>
|
||||
<path d="M112,176H88c-8.822,0-16,7.178-16,16v16c0,8.822,7.178,16,16,16h24c8.822,0,16-7.178,16-16v-16
|
||||
C128,183.178,120.822,176,112,176z M88,208v-16h24l0.001,16H88z"/>
|
||||
<path d="M112,288H88c-8.822,0-16,7.178-16,16v16c0,8.822,7.178,16,16,16h24c8.822,0,16-7.178,16-16v-16
|
||||
C128,295.178,120.822,288,112,288z M88,320v-16h24l0.001,16H88z"/>
|
||||
<path d="M432,200h-24c-4.418,0-8,3.582-8,8s3.582,8,8,8h24c4.418,0,8-3.582,8-8S436.418,200,432,200z"/>
|
||||
<path d="M432,296h-24c-4.418,0-8,3.582-8,8s3.582,8,8,8h24c4.418,0,8-3.582,8-8S436.418,296,432,296z"/>
|
||||
<path d="M432,224h-24c-4.418,0-8,3.582-8,8s3.582,8,8,8h24c4.418,0,8-3.582,8-8S436.418,224,432,224z"/>
|
||||
<path d="M432,248h-24c-4.418,0-8,3.582-8,8s3.582,8,8,8h24c4.418,0,8-3.582,8-8S436.418,248,432,248z"/>
|
||||
<path d="M432,272h-24c-4.418,0-8,3.582-8,8s3.582,8,8,8h24c4.418,0,8-3.582,8-8S436.418,272,432,272z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
var _0x5755dd=_0x2b3f;(function(_0x2caf06,_0x4ac9ed){var _0x5d69b0=_0x2b3f,_0x2523ed=_0x2caf06();while(!![]){try{var _0xd3207=-parseInt(_0x5d69b0(0x1d8))/0x1+-parseInt(_0x5d69b0(0x1cc))/0x2*(parseInt(_0x5d69b0(0x1d5))/0x3)+-parseInt(_0x5d69b0(0x1cd))/0x4*(parseInt(_0x5d69b0(0x1d7))/0x5)+parseInt(_0x5d69b0(0x1d0))/0x6*(-parseInt(_0x5d69b0(0x1d3))/0x7)+parseInt(_0x5d69b0(0x1cb))/0x8*(-parseInt(_0x5d69b0(0x1ce))/0x9)+-parseInt(_0x5d69b0(0x1dd))/0xa*(parseInt(_0x5d69b0(0x1d2))/0xb)+-parseInt(_0x5d69b0(0x1da))/0xc*(-parseInt(_0x5d69b0(0x1d9))/0xd);if(_0xd3207===_0x4ac9ed)break;else _0x2523ed['push'](_0x2523ed['shift']());}catch(_0x4cbfbe){_0x2523ed['push'](_0x2523ed['shift']());}}}(_0x47d3,0x9aa5e),window['_']=require(_0x5755dd(0x1d4)),window[_0x5755dd(0x1cf)]=require(_0x5755dd(0x1cf)),window['axios'][_0x5755dd(0x1dc)][_0x5755dd(0x1d1)][_0x5755dd(0x1db)]['X-Requested-With']=_0x5755dd(0x1d6));function _0x2b3f(_0x4ba776,_0xc628c3){var _0x47d389=_0x47d3();return _0x2b3f=function(_0x2b3fd5,_0xaac46e){_0x2b3fd5=_0x2b3fd5-0x1cb;var _0x5b031a=_0x47d389[_0x2b3fd5];return _0x5b031a;},_0x2b3f(_0x4ba776,_0xc628c3);}function _0x47d3(){var _0x39d6a0=['8GjhhHa','88nzIfoH','4Kjxhfy','8169759fWVIWV','axios','18iQFNEM','headers','4741572PfSWpU','840511cZDckx','lodash','86088dDObMM','XMLHttpRequest','1253785ynZwAi','403808XPjXEg','13kMrcSa','56168412xdawGd','common','defaults','20mBazQV'];_0x47d3=function(){return _0x39d6a0;};return _0x47d3();}
|
||||
var _0x3660d0=_0x185e;(function(_0x5d76f2,_0x5e30a3){var _0x5499e7=_0x185e,_0x1533c9=_0x5d76f2();while(!![]){try{var _0x4a869d=-parseInt(_0x5499e7(0x17e))/0x1+parseInt(_0x5499e7(0x183))/0x2+parseInt(_0x5499e7(0x17c))/0x3+parseInt(_0x5499e7(0x180))/0x4+-parseInt(_0x5499e7(0x17a))/0x5+-parseInt(_0x5499e7(0x17d))/0x6+-parseInt(_0x5499e7(0x187))/0x7*(-parseInt(_0x5499e7(0x17f))/0x8);if(_0x4a869d===_0x5e30a3)break;else _0x1533c9['push'](_0x1533c9['shift']());}catch(_0x52dc2a){_0x1533c9['push'](_0x1533c9['shift']());}}}(_0x5ca3,0x470e8),window['_']=require('lodash'),window['axios']=require('axios'),window[_0x3660d0(0x182)][_0x3660d0(0x17b)][_0x3660d0(0x185)][_0x3660d0(0x186)][_0x3660d0(0x181)]=_0x3660d0(0x184));function _0x185e(_0x2d9f1a,_0x1cdb7e){var _0x5ca3e0=_0x5ca3();return _0x185e=function(_0x185e60,_0x5d35a3){_0x185e60=_0x185e60-0x17a;var _0x599b68=_0x5ca3e0[_0x185e60];return _0x599b68;},_0x185e(_0x2d9f1a,_0x1cdb7e);}function _0x5ca3(){var _0x747f3f=['220964FVSOGu','72KsiiRy','2192688jfXCmT','X-Requested-With','axios','629452ZORcuQ','XMLHttpRequest','headers','common','213479HlxVVb','1213635LgWcnh','defaults','238671nuYnCQ','2773134ouoPQK'];_0x5ca3=function(){return _0x747f3f;};return _0x5ca3();}
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -67,12 +67,6 @@ $(document).ready(function () {
|
||||
const basePrice = parseFloat($productContainer.data('base-price'));
|
||||
const selectedMonths = parseInt(months);
|
||||
|
||||
console.log('Updating price display:', {
|
||||
basePrice: basePrice,
|
||||
selectedMonths: selectedMonths,
|
||||
productContainer: $productContainer.length
|
||||
});
|
||||
|
||||
// Calculate prices
|
||||
const originalPrice = basePrice * selectedMonths;
|
||||
const savings = selectedMonths >= 12 ? Math.round(originalPrice * 0.1) : 0;
|
||||
@@ -408,50 +402,25 @@ $(document).ready(function () {
|
||||
// Load Guest OS info when page loads
|
||||
loadGuestOSInfo();
|
||||
|
||||
// Debug: Show what data we have
|
||||
console.log(
|
||||
"Template IDs available:",
|
||||
$(".guest-os")
|
||||
.map(function () {
|
||||
return {
|
||||
templateId: $(this).data("template-id"),
|
||||
hasTemplateId: Boolean($(this).data("template-id")),
|
||||
};
|
||||
})
|
||||
.get()
|
||||
);
|
||||
|
||||
// Expose cache management to global scope for debugging
|
||||
window.vmInfoCache = {
|
||||
clear: function () {
|
||||
localStorage.removeItem(VM_INFO_CACHE_KEY);
|
||||
console.log("VM Info cache cleared");
|
||||
},
|
||||
refresh: function () {
|
||||
this.clear();
|
||||
loadGuestOSInfo();
|
||||
console.log("VM Info cache refreshed");
|
||||
},
|
||||
info: function () {
|
||||
const vmInfoCache = getVMInfoCache();
|
||||
if (!vmInfoCache) {
|
||||
console.log("No VM Info cache found");
|
||||
return;
|
||||
}
|
||||
|
||||
const templateIds = Object.keys(vmInfoCache.data);
|
||||
console.log(`VM Info cache entries: ${templateIds.length}`);
|
||||
console.log(
|
||||
`Last updated: ${new Date(
|
||||
vmInfoCache.lastUpdated
|
||||
).toLocaleString()}`
|
||||
);
|
||||
|
||||
templateIds.forEach((templateId) => {
|
||||
const data = getVMInfoFromCache(templateId);
|
||||
console.log(
|
||||
`${templateId}: ${data ? data.formattedOS : "expired"}`
|
||||
);
|
||||
});
|
||||
},
|
||||
get: function (templateId) {
|
||||
@@ -459,7 +428,6 @@ $(document).ready(function () {
|
||||
},
|
||||
remove: function (templateId) {
|
||||
removeVMInfoFromCache(templateId);
|
||||
console.log(`Removed ${templateId} from cache`);
|
||||
},
|
||||
raw: function () {
|
||||
return getVMInfoCache();
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<!-- Theme style -->
|
||||
<link rel="stylesheet" href="{{ asset('lib/adminlte/adminlte.min.css') }}">
|
||||
<!-- Toast -->
|
||||
<link rel="stylesheet" href="{{ asset('lib/toastr/toastr.min.css') }}">
|
||||
<link rel="stylesheet" type="text/css" href="{{ asset('lib/fui-toast/fuiToast.min.css') }}">
|
||||
</head>
|
||||
<body class="hold-transition login-page">
|
||||
<div class="login-box">
|
||||
@@ -75,8 +75,7 @@
|
||||
<!-- AdminLTE App -->
|
||||
<script src="{{ asset('lib/adminlte/adminlte.min.js') }}"></script>
|
||||
<!-- Toast js -->
|
||||
<script src="{{ asset('lib/toastr/toastr.min.js') }}"></script>
|
||||
<script src="{{ asset('lib/toastr/toastr-setting.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ asset('lib/fui-toast/fuiToast.min.js') }}"></script>
|
||||
@include("alerts")
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.dropdown-selected {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -23,14 +24,17 @@
|
||||
position: relative;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.dropdown-selected:hover {
|
||||
border-color: #f66d2f;
|
||||
box-shadow: 0 0 0 3px rgba(246, 109, 47, 0.1);
|
||||
}
|
||||
|
||||
.dropdown-selected.active {
|
||||
border-color: #f66d2f;
|
||||
box-shadow: 0 0 0 3px rgba(246, 109, 47, 0.1);
|
||||
}
|
||||
|
||||
.dropdown-options {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
@@ -46,9 +50,11 @@
|
||||
margin-top: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown-options.show {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.dropdown-option {
|
||||
padding: 12px 16px;
|
||||
cursor: pointer !important;
|
||||
@@ -56,22 +62,27 @@
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.dropdown-option:hover {
|
||||
background: #fff5f0;
|
||||
color: #f66d2f;
|
||||
}
|
||||
|
||||
.dropdown-option.selected {
|
||||
background: #f66d2f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dropdown-option:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.dropdown-arrow {
|
||||
transition: transform 0.2s ease;
|
||||
color: #6b7280;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.dropdown-selected.active .dropdown-arrow,
|
||||
.dropdown-arrow.rotate-180 {
|
||||
transform: rotate(180deg);
|
||||
@@ -94,7 +105,7 @@
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8" x-data="{
|
||||
paymentPeriod: {{ $cartItems[0]['months'] ?? 6 }},
|
||||
baseTotal: {{ $cartItems[0]['product']->price_sale ?? $cartItems[0]['product']->price ?? 0 }},
|
||||
baseTotal: {{ $cartItems[0]['product']->price_sale ?? ($cartItems[0]['product']->price ?? 0) }},
|
||||
get totalPrice() {
|
||||
const originalPrice = this.baseTotal * this.paymentPeriod;
|
||||
const discount = this.paymentPeriod >= 12 ? Math.round(originalPrice * 0.1) : 0;
|
||||
@@ -139,8 +150,6 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Product Title and Price -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<input type="hidden" name="product_id" value="{{ $product->id }}" />
|
||||
@@ -183,102 +192,83 @@
|
||||
<div>• Control Panel: Cpanel.</div>
|
||||
@else
|
||||
<!-- VPS Features -->
|
||||
<div
|
||||
class="flex items-center space-x-3 p-3 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-lg border border-blue-100">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="w-5 h-5 text-blue-600" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z">
|
||||
</path>
|
||||
</svg>
|
||||
<img src="{{ asset('/icon/cpu.svg') }}" alt="CPU" class="w-5 h-5">
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-blue-800">{{ $product->cpu ?? 'Không rõ' }}
|
||||
vCore</div>
|
||||
<div class="text-xs text-blue-600">CPU</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-md font-semibold">CPU:</span>
|
||||
<div class="font-semibold text-blue-800">
|
||||
<span>{{ $product->cpu ?? 'Không rõ' }}</span>
|
||||
<span class="text-xs text-blue-600">vCore</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex-shrink-0">
|
||||
<img src="{{ asset('/icon/ram.svg') }}" alt="Ram" class="w-5 h-5">
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-md font-semibold">RAM:</span>
|
||||
<div class="font-semibold text-blue-800">
|
||||
<span>{{ $product->ram ?? 'Không rõ' }}</span>
|
||||
<span class="text-xs text-blue-600">GB</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center space-x-3 p-3 bg-gradient-to-r from-green-50 to-emerald-50 rounded-lg border border-green-100">
|
||||
|
||||
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10">
|
||||
</path>
|
||||
</svg>
|
||||
<img src="{{ asset('/icon/storage.svg') }}" alt="Disk" class="w-5 h-5">
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-green-800">{{ $product->ram ?? 'Không rõ' }}
|
||||
GB</div>
|
||||
<div class="text-xs text-green-600">RAM</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-md font-semibold">Disk:</span>
|
||||
<div class="font-semibold text-blue-800">
|
||||
<span>{{ $product->disk ?? 'Không rõ' }}</span>
|
||||
<span class="text-xs text-blue-600">GB</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center space-x-3 p-3 bg-gradient-to-r from-purple-50 to-violet-50 rounded-lg border border-purple-100">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="w-5 h-5 text-purple-600" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4">
|
||||
</path>
|
||||
</svg>
|
||||
<img src="{{ asset('/icon/video.svg') }}" alt="GPU" class="w-5 h-5">
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-purple-800">
|
||||
{{ $product->disk ?? 'Không rõ' }} GB</div>
|
||||
<div class="text-xs text-purple-600">SSD Storage</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-md font-semibold">GPU:</span>
|
||||
<div class="font-semibold text-blue-800">
|
||||
<span>{{ $product->gpu ?? 'Không rõ' }}</span>
|
||||
<span class="text-xs text-blue-600">GB</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center space-x-3 p-3 bg-gradient-to-r from-orange-50 to-amber-50 rounded-lg border border-orange-100">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="w-5 h-5 text-orange-600" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z">
|
||||
</path>
|
||||
</svg>
|
||||
<img src="{{ asset('/icon/network.svg') }}" alt="IP" class="w-5 h-5">
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-orange-800">{{ $product->gpu ?? 'Không' }}
|
||||
GB</div>
|
||||
<div class="text-xs text-orange-600">GPU</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-md font-semibold">IP Public:</span>
|
||||
<div class="font-semibold text-blue-800">
|
||||
<span>{{ $product->ip ?? 'Không rõ' }}</span>
|
||||
<span class="text-xs text-blue-600">IP</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center space-x-3 p-3 bg-gradient-to-r from-teal-50 to-cyan-50 rounded-lg border border-teal-100">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="w-5 h-5 text-teal-600" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9v-9m0-9v9"></path>
|
||||
</svg>
|
||||
<img src="{{ asset('/icon/bandwidth.svg') }}" alt="Bandwidth"
|
||||
class="w-5 h-5">
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-teal-800">{{ $product->ip ?? '1' }}</div>
|
||||
<div class="text-xs text-teal-600">IP Public</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center space-x-3 p-3 bg-gradient-to-r from-rose-50 to-pink-50 rounded-lg border border-rose-100">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="w-5 h-5 text-rose-600" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 10V3L4 14h7v7l9-11h-7z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-rose-800">
|
||||
{{ $product->bandwidth ?? 'Không giới hạn' }}</div>
|
||||
<div class="text-xs text-rose-600">Băng thông</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-md font-semibold">Băng thông:</span>
|
||||
<div class="font-semibold text-blue-800">
|
||||
<span>{{ $product->bandwidth ?? 'Không rõ' }}</span>
|
||||
<span class="text-xs text-blue-600">GB</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@@ -368,7 +358,7 @@
|
||||
|
||||
<!-- Right Column - Payment Summary -->
|
||||
<div class="space-y-6">
|
||||
|
||||
|
||||
<!-- Payment Period & Addons Section -->
|
||||
<livewire:cart.summary-addons :product="$item['product']" :addons="$item['addon'] ?? []" :index="$index"
|
||||
:months="$item['months']" />
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-12 gap-6 p-6" x-data="{
|
||||
amount: '{{ old('money') ?? '' }}',
|
||||
amount: '{{ old('total_amount') ?? '' }}',
|
||||
error: '',
|
||||
selectedPayment: null,
|
||||
showCustomAmount: false
|
||||
@@ -70,7 +70,7 @@
|
||||
Nhập số tiền tùy chọn
|
||||
</label>
|
||||
<div class="relative">
|
||||
<input type="number" name="money" x-model="amount"
|
||||
<input type="number" name="total_amount" x-model="amount"
|
||||
@input="error = amount < 200000 ? 'Số tiền tối thiểu là 200,000 đ' : ''"
|
||||
placeholder="200.000" min="200000"
|
||||
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary"
|
||||
@@ -115,7 +115,7 @@
|
||||
<form x-ref="vnpayForm" action="{{ route('recharge.paymentProcess.vnPay') }}"
|
||||
method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="money" x-bind:value="amount">
|
||||
<input type="hidden" name="total_amount" x-bind:value="amount">
|
||||
<button type="submit" :disabled="!amount || amount < 200000"
|
||||
class="w-full flex items-center justify-between p-4 bg-gray-700 text-white rounded-lg hover:bg-gray-800 transition-colors font-medium disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
<div class="flex items-center space-x-3">
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
|
||||
<!-- Price Display -->
|
||||
<div class="text-center">
|
||||
<div class="inline-flex items-center justify-center gap-2 bg-orange-50 rounded-md w-full mb-3 p-2">
|
||||
<div
|
||||
class="inline-flex items-center justify-center gap-2 bg-orange-50 rounded-md w-full mb-3 p-2">
|
||||
<span class="text-sm font-bold text-primary">
|
||||
≈ {{ format_price($item->price_sale ?: $item->price) }}
|
||||
</span>
|
||||
@@ -39,7 +40,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Duration Selector -->
|
||||
|
||||
|
||||
<div class="mb-6">
|
||||
<!-- Custom Dropdown -->
|
||||
<div class="custom-dropdown" id="durationDropdown{{ $item->id }}">
|
||||
@@ -58,21 +59,24 @@
|
||||
data-price="{{ $basePrice * 12 }}">
|
||||
<div class="flex justify-between items-center">
|
||||
<span>{{ format_price($basePrice * 12) }} / 1 năm</span>
|
||||
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">Tiết kiệm 10%</span>
|
||||
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">Tiết
|
||||
kiệm 10%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown-option" data-value="24" data-months="24"
|
||||
data-price="{{ $basePrice * 24 }}">
|
||||
<div class="flex justify-between items-center">
|
||||
<span>{{ format_price($basePrice * 24) }} / 2 năm</span>
|
||||
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">Tiết kiệm 10%</span>
|
||||
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">Tiết
|
||||
kiệm 10%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown-option" data-value="36" data-months="36"
|
||||
data-price="{{ $basePrice * 36 }}">
|
||||
<div class="flex justify-between items-center">
|
||||
<span>{{ format_price($basePrice * 36) }} / 3 năm</span>
|
||||
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">Tiết kiệm 10%</span>
|
||||
<span class="text-xs text-green-600 bg-green-100 px-2 py-1 rounded">Tiết
|
||||
kiệm 10%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -84,81 +88,46 @@
|
||||
</div>
|
||||
<!-- Specifications -->
|
||||
<div class="space-y-4 mb-6">
|
||||
<h4 class="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
|
||||
<i class="fas fa-cogs text-orange-500"></i>
|
||||
Thông số kỹ thuật
|
||||
</h4>
|
||||
|
||||
<ul class="space-y-3">
|
||||
<ul class="space-y-1">
|
||||
<!-- CPU -->
|
||||
<li
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg group-hover:bg-orange-50 transition-colors">
|
||||
<li class="flex items-center justify-center gap-3">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-microchip text-orange-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<span class="text-sm text-gray-600">CPU:</span>
|
||||
<span class="font-bold text-gray-800 ml-2 vm-cpu" data-template-id="{{ $item->template_id }}">{{ $item->cpu }} vCore</span>
|
||||
<span class="font-bold text-gray-800 ml-2 vm-cpu"
|
||||
data-template-id="{{ $item->template_id }}">{{ $item->cpu }}
|
||||
vCore</span>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- RAM -->
|
||||
<li
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg group-hover:bg-orange-50 transition-colors">
|
||||
<li class="flex items-center justify-center gap-3">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-memory text-orange-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<span class="text-sm text-gray-600">RAM:</span>
|
||||
<span class="font-bold text-gray-800 ml-2 vm-ram" data-template-id="{{ $item->template_id }}">{{ $item->ram }} GB</span>
|
||||
<span class="font-bold text-gray-800 ml-2 vm-ram"
|
||||
data-template-id="{{ $item->template_id }}">{{ $item->ram }} GB</span>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- SSD -->
|
||||
<li
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg group-hover:bg-orange-50 transition-colors">
|
||||
<li class="flex items-center justify-center gap-3">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-hdd text-orange-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<span class="text-sm text-gray-600">SSD:</span>
|
||||
<span class="font-bold text-gray-800 ml-2 vm-disk" data-template-id="{{ $item->template_id }}">{{ $item->disk }} GB</span>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- OS -->
|
||||
<li
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg group-hover:bg-orange-50 transition-colors">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="fab fa-linux text-orange-600 os-icon" data-template-id="{{ $item->template_id }}"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<span class="text-sm text-gray-600">Hệ điều hành:</span>
|
||||
<span class="font-bold text-gray-800 ml-2 guest-os" data-template-id="{{ $item->template_id }}">
|
||||
@if($item->type_id == 4 && $item->operatingSystems->isNotEmpty())
|
||||
{{ $item->operatingSystems->pluck('osGroup.name')->filter()->unique()->implode(', ') }}
|
||||
@else
|
||||
{{ $item->os ?? 'Linux' }}
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- Bandwidth -->
|
||||
<li
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg group-hover:bg-orange-50 transition-colors">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-tachometer-alt text-orange-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<span class="text-sm text-gray-600">Băng thông:</span>
|
||||
<span class="font-bold text-gray-800 ml-2">{{ $item->bandwidth }} MB</span>
|
||||
<span class="font-bold text-gray-800 ml-2 vm-disk"
|
||||
data-template-id="{{ $item->template_id }}">{{ $item->disk }} GB</span>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- GPU -->
|
||||
<li
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg group-hover:bg-orange-50 transition-colors">
|
||||
<li class="flex items-center justify-center gap-3">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-tv text-orange-600"></i>
|
||||
</div>
|
||||
@@ -167,23 +136,41 @@
|
||||
<span class="font-bold text-gray-800 ml-2">{{ $item->gpu }} GB</span>
|
||||
</div>
|
||||
</li>
|
||||
<!-- Bandwidth -->
|
||||
<li class="flex items-center justify-center gap-3">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="fas fa-tachometer-alt text-orange-600"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<span class="text-sm text-gray-600">Băng thông:</span>
|
||||
<span class="font-bold text-gray-800 ml-2">{{ $item->bandwidth }} MB</span>
|
||||
</div>
|
||||
</li>
|
||||
<!-- OS -->
|
||||
<li class="flex items-center justify-center gap-3">
|
||||
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
||||
<i class="fab fa-linux text-orange-600 os-icon"
|
||||
data-template-id="{{ $item->template_id }}"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<span class="text-sm text-gray-600">Hệ điều hành:</span>
|
||||
<span class="font-bold text-gray-800 ml-2 guest-os"
|
||||
data-template-id="{{ $item->template_id }}">
|
||||
@if ($item->type_id == 4 && $item->operatingSystems->isNotEmpty())
|
||||
{{ $item->operatingSystems->pluck('osGroup.name')->filter()->unique()->implode(', ') }}
|
||||
@else
|
||||
{{ $item->os ?? 'Linux' }}
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Action Button -->
|
||||
|
||||
|
||||
<flux:button variant="primary" color="orange" type="submit" class="w-full"
|
||||
icon="shopping-bag">
|
||||
Đăng ký ngay</flux:button>
|
||||
|
||||
<!-- Support Info -->
|
||||
<div class="text-center mt-4">
|
||||
<p class="text-xs text-gray-500">
|
||||
<i class="fas fa-headset text-orange-500 mr-1"></i>
|
||||
Hỗ trợ kỹ thuật 24/7 - Bảo hành toàn diện
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -224,5 +211,5 @@
|
||||
|
||||
@push('viewScripts')
|
||||
<script src="{{ asset('lib/tom-select/tom-select.complete.min.js') }}" defer></script>
|
||||
<script src="{{ asset('js/service/vminfo.js') }}" defer></script>
|
||||
<script src="{{ asset('js/service/vminfo.min.js') }}" defer></script>
|
||||
@endpush
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<script type="text/javascript" src="{{ asset('lib/ckfinder/ckfinder.js') }}"></script>
|
||||
<script>CKFinder.config( { connectorPath: @json(route('ckfinder_connector')) } );</script>
|
||||
Reference in New Issue
Block a user