🆙 Add fixed cms 🆙

This commit is contained in:
Remco
2026-02-02 19:30:21 +01:00
parent b1a2cab62d
commit b67e0ec2b9
3982 changed files with 193682 additions and 0 deletions
@@ -0,0 +1,135 @@
<x-app-layout>
@push('title', auth()->user()->username)
<div class="col-span-12 space-y-3 md:col-span-9">
<x-user.me-backdrop :user="$user" />
<div
class="flex flex-col gap-3 rounded border bg-white p-1 shadow-sm dark:border-gray-900 dark:bg-gray-800 lg:flex-row lg:items-center lg:justify-between">
<div
class="relative flex items-center justify-center rounded bg-[#e9b124] py-2 px-2 text-sm font-semibold dark:text-gray-300 dark:border-gray-700 lg:self-stretch">
<div class="invisible h-6 w-6 -right-1 rotate-45 bg-[#e9b124] lg:visible lg:absolute"></div>
<img src="{{ asset('/assets/images/icons/online-friends.png') }}" alt="{{ __('Online Friends') }}"
class="mr-2 mb-1 inline-flex" style="max-width: 24px; max-height: 24px">
<span class="relative text-white">{{ __('Online Friends') }}</span>
</div>
<div class="relative flex flex-wrap items-center justify-center gap-2 pl-2 sm:justify-start">
@foreach ($onlineFriends as $friend)
<div data-popover-target="friend-{{ $friend->username }}"
style="image-rendering: pixelated; background-image: url({{ setting('avatar_imager') }}{{ $friend->look }}&direction=2&head_direction=3&gesture=sml&action=wav&headonly=1&size=s)"
class="inline-block h-10 w-10 rounded-full border-2 border-gray-300 bg-center bg-no-repeat dark:border-gray-900">
</div>
<div data-popover id="friend-{{ $friend->username }}" role="tooltip"
class="invisible absolute z-10 inline-block w-64 rounded-lg border border-gray-200 bg-white text-sm font-light text-gray-500 opacity-0 shadow-xs transition-opacity duration-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400">
<div
class="rounded-t-lg border-b border-gray-200 bg-gray-100 px-3 py-2 dark:border-gray-600 dark:bg-gray-700">
<div
class="flex w-full items-center justify-center font-semibold text-gray-900 dark:text-white">
{{ $friend->username }}
</div>
</div>
<div class="overflow-y-auto px-3 py-2" style="max-height: 200px">
<b class="mr-1 font-bold">{{ __('Motto') }}:</b>{{ $friend->motto }}<br>
<b
class="mr-1 font-bold">{{ __('Online Since') }}
:</b>{{ date(config('habbo.site.date_format'), $friend->last_online) }}
</div>
<div data-popper-arrow></div>
</div>
@endforeach
</div>
</div>
<x-content.content-card icon="friends-icon" classes="border dark:border-gray-900">
<x-slot:title>
{{ sprintf(__('User Referrals (%s/%s)'), auth()->user()->referrals->referrals_total ?? 0, setting('referrals_needed')) }}
</x-slot:title>
<x-slot:under-title>
{{ __('Referral new users and be rewarded by in-game goods') }}
</x-slot:under-title>
<div class="px-2 text-sm dark:text-gray-200">
{{ __('Here at :hotel we have added a referral system, allowing you to obtain a bonus for every :needed users that registers through your referral link will allow you to claim a reward of :amount diamonds!', ['hotel' => setting('hotel_name'), 'needed' => setting('referrals_needed'), 'amount' => setting('referral_reward_amount')]) }}
<br>
<small class="text-gray-400">
{{ __('Boosting referrals by making own accounts will lead to removal of all progress, currency, inventory and a potential ban') }}
</small>
<div class="grid grid-cols-12 gap-2">
<x-form.input classes="col-span-12 md:col-span-10 text-sm" name="referral"
value="{{ sprintf('%s/register/%s', config('habbo.site.site_url'), auth()->user()->referral_code) }}"
:autofocus="false" :readonly="true" />
<div class="col-span-12 flex md:col-span-2" onclick="copyCode()">
<x-form.secondary-button>
{{ __('Copy code') }}
</x-form.secondary-button>
</div>
</div>
@if (auth()->user()->referrals?->referrals_total >= (int) setting('referrals_needed'))
<a href="{{ route('claim.referral-reward') }}" class="text-decoration-none">
<x-form.secondary-button classes="mt-2">
{{ __('Claim your referrals reward!') }}
</x-form.secondary-button>
</a>
@else
<button disabled class="mt-2 w-full rounded bg-gray-400 p-2 text-white dark:bg-gray-900">
{{ sprintf(__('You need to refer :needed more users, before being able to claim your reward', ['needed' =>auth()->user()->referralsNeeded() ?? 0]),auth()->user()->referrals->referrals_total ?? 0) }}
</button>
@endif
</div>
</x-content.content-card>
</div>
<div class="col-span-12 space-y-4 md:col-span-3">
<div class="relative w-full" style="height: 213px">
<div class="relative swiper articles-slider">
<div class="swiper-wrapper">
@forelse ($articles as $article)
<x-article-card :for-slider="true" :article="$article" />
@empty
<x-filler-article-card />
@endforelse
</div>
</div>
<div class="swiper-pagination" style="bottom: 0px !important; z-index: 0;"></div>
</div>
<div class="!mt-3">
<x-user.discord-widget />
</div>
</div>
@push('javascript')
<script>
var Toast = Swal.mixin({
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 4000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener("mouseenter", Swal.stopTimer);
toast.addEventListener("mouseleave", Swal.resumeTimer);
}
});
function copyCode() {
let copyText = document.querySelector("#referral");
copyText.select();
document.execCommand("copy");
Toast.fire({
icon: "success",
title: '{{ __('Your referral code has been copied to your clipbord!') }}'
});
}
</script>
@endpush
</x-app-layout>
@@ -0,0 +1,210 @@
<x-app-layout>
@push('title', $user->username)
<div class="col-span-12">
<div class="grid grid-cols-1! gap-y-14">
<div class="grid grid-cols-3! gap-x-8">
<div
class="col-span-3 md:col-span-1! h-[150px] lg:h-[220px] profile-bg rounded-lg relative flex gap-x-2 items-center text-white overflow-hidden">
<img class="mt-14 drop-shadow lg:mt-0" style="image-rendering: pixelated;"
src="{{ setting('avatar_imager') }}{{ $user->look }}&direction=2&head_direction=3&gesture=sml&action=wav&size=l"
alt="">
<div class="flex flex-col">
<h3 class="text-xl font-semibold">{{ __('My name is,') }}</h3>
<h2 class="text-4xl">
{{ $user->username }}
</h2>
<h4 class="text-lg font-semibold italic">{{ $user->motto }}</h4>
</div>
</div>
<div
class="col-span-3! mt-4 grid w-full grid-cols-1 space-y-3 md:space-y-0 md:col-span-2! md:mt-0 md:grid-cols-3">
<div
class="rounded-lg md:rounded-none md:rounded-l-lg bg-[#f8ef2b] flex flex-col gap-y-2 items-center justify-center py-3 md:py-0">
<img src="{{ asset('/assets/images/profile/credits.png') }}" alt="">
<h4 class="text-[#b16d18] font-semibold text-2xl">
{{ $user->credits }}
</h4>
</div>
<div
class="rounded-lg md:rounded-none bg-[#e99bdc] flex flex-col gap-y-2 items-center justify-center py-3 md:py-0">
<img src="{{ asset('/assets/images/profile/duckets.png') }}" alt="">
<h4 class="text-[#812378] font-semibold text-2xl">
{{ $user->currency('duckets') }}
</h4>
</div>
<div
class="rounded-lg md:rounded-none md:rounded-r-lg! bg-[#82d6db] flex flex-col gap-y-2 items-center justify-center py-3 md:py-0">
<img src="{{ asset('/assets/images/profile/diamonds.png') }}" alt="">
<h4 class="text-[#146867] font-semibold text-2xl">
{{ $user->currency('diamonds') }}
</h4>
</div>
</div>
</div>
<div class="grid gap-14 grid-cols-1 md:grid-cols-2">
<div class="col-span-1">
<x-user.profile-info-card col-span="1">
<x-slot:image>
<img class="h-[140px] object-cover object-left" src="{{ asset('/assets/images/profile/badges.png') }}" alt="">
</x-slot:image>
<x-slot:title>
{{ __('Badges') }}
</x-slot:title>
<div class="flex flex-wrap gap-2 justify-between">
@forelse($user->badges as $badge)
<div data-tippy-content="{{ $badge->badge_code }}"
class="user-badge h-[70px] w-[70px] border-2 dark:border-gray-700 rounded-full flex items-center justify-center cursor-pointer">
<img src="{{ setting('badges_path') }}/{{ $badge->badge_code }}.gif"
class="max-h-[55px] max-w-[55px]" alt="">
</div>
@empty
<div class="col-span-4">
{{ __('It seems like :user has no badges.', ['user' => $user->username]) }}
</div>
@endforelse
</div>
</x-user.profile-info-card>
</div>
<div class="col-span-1">
<x-user.profile-info-card col-span="1">
<x-slot:image>
<img class="h-[140px] object-cover object-left" src="{{ asset('/assets/images/profile/groups.png') }}" alt="">
</x-slot:image>
<x-slot:title>
{{ __('Groups') }}
</x-slot:title>
<div class="flex flex-wrap gap-4 justify-between">
@forelse($groups as $group)
<div class="h-[70px] w-[70px] rounded-full border-2 dark:border-gray-700 overflow-hidden flex items-center justify-center p-1 rounded-md cursor-pointer friend"
data-tippy-content="{{ $group->name ?? 'Unknown' }}">
<img src="{{ setting('group_badge_path') }}/{{ $group->badge }}.png"
alt="">
</div>
@empty
<div class="w-full">
{{ __('It seems like :user is not a member of any groups.', ['user' => $user->username]) }}
</div>
@endforelse
</div>
</x-user.profile-info-card>
</div>
</div>
<div class="grid gap-14 grid-cols-1 md:grid-cols-2">
<div class="col-span-1">
<x-user.profile-info-card col-span="1">
<x-slot:image>
<img class="h-[140px] object-cover object-left" src="{{ asset('/assets/images/profile/rooms.png') }}" alt="">
</x-slot:image>
<x-slot:title>
{{ __('Rooms') }}
</x-slot:title>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 space-x-1">
@forelse($user->rooms as $room)
<div
class="flex flex-col gap-y-1 rounded-md dark:bg-gray-900 bg-gray-200 p-1 overflow-hidden">
<div class="h-full inline-block">
<div class="h-full relative border border-gray-500 dark:border-gray-700 rounded flex items-center justify-center flex-col">
<img
class="rounded mt-1 mb-1"
src="{{ setting('room_thumbnail_path') }}/{{ $room->id }}.png"
alt="{{ $room->name }}"
onerror="this.onerror=null;this.src='{{ asset('/assets/images/profile/room_placeholder.png') }}';"
>
<div class="absolute bottom-1 left-1/2 transform -translate-x-1/2">
<div class="{{ $room->users > 0 ? 'bg-[#00800B]' : 'bg-gray-400' }} px-1 py-[1px] font-semibold rounded flex gap-x-[3px] text-white items-center text-xs">
<svg xmlns="http://www.w3.org/2000/svg" class="h-[12px]" viewBox="0 0 20 20" fill="currentColor">
<path
fill-rule="evenodd"
d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
clip-rule="evenodd"
/>
</svg>
{{ $room->users }}
</div>
</div>
</div>
</div>
<div class="flex items-center justify-between px-1">
<p class="truncate">{{ Str::limit($room->name, 6) }}</p>
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 text-cyan-300 hover:text-cyan-400"
viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
clip-rule="evenodd" />
</svg>
</a>
</div>
</div>
@empty
<div class="col-span-4">
{{ __('It seems like :user got no rooms.', ['user' => $user->username]) }}
</div>
@endforelse
</div>
</x-user.profile-info-card>
</div>
<div class="col-span-1">
<x-user.profile-info-card col-span="1">
<x-slot:image>
<img class="h-[140px] object-cover object-left" src="{{ asset('/assets/images/profile/friends.png') }}" alt="">
</x-slot:image>
<x-slot:title>
{{ __('Friends') }}
</x-slot:title>
<div class="grid grid-cols-4 gap-2 xl:grid-cols-6 xl:pl-3">
@forelse($friends as $friend)
<a href="{{ route('profile.show', $friend->user->username ?? 'SystemAccount') }}"
class="h-[70px] w-[70px] rounded-full border-2 dark:border-gray-700 overflow-hidden flex items-center p-1 rounded-md cursor-pointer friend"
data-tippy-content="{{ $friend->user->username ?? 'Unknown' }}">
<img class="mt-6 transition duration-200 ease-in-out hover:scale-110 min-w-[64px] h-[110px] -ml-1"
src="{{ setting('avatar_imager') }}{{ $friend->user?->look }}"
alt="">
</a>
@empty
<div class="col-span-6">
{{ __('It seems like :user has no friends.', ['user' => $user->username]) }}
</div>
@endforelse
</div>
</x-user.profile-info-card>
</div>
</div>
</div>
</div>
@push('javascript')
<script type="module">
tippy('.user-badge');
tippy('.friend');
tippy('.group');
</script>
@endpush
</x-app-layout>
@@ -0,0 +1,76 @@
<x-app-layout>
@push('title', __('Account settings'))
<div class="col-span-12 flex flex-col gap-y-3 md:col-span-3">
<x-user.settings.settings-navigation />
</div>
<div class="col-span-12 flex flex-col gap-y-3 md:col-span-9">
<x-content.content-card icon="hotel-icon" classes="border dark:border-gray-900">
<x-slot:title>
{{ __('Account settings') }}
</x-slot:title>
<x-slot:under-title>
{{ __('Manage your account settings') }}
</x-slot:under-title>
<form action="{{ route('settings.account.update') }}" method="POST" class="flex flex-col gap-y-4">
@method('PUT')
@csrf
<div class="flex flex-col gap-y-1">
<x-form.label for="mail">
{{ __('E-mail') }}
<x-slot:info>
{{ __('Make sure to use an email that you remember, if you ever lose your password, your email will be required.') }}
</x-slot:info>
</x-form.label>
<x-form.input name="mail" type="email" value="{{ $user->mail }}" :autofocus="true" />
</div>
@if ($user->settings?->allow_name_change)
<div class="flex flex-col gap-y-1">
<x-form.label for="username">
{{ __('Username') }}
<x-slot:info>
{{ __('Your username is what you and others will see in-game') }}
</x-slot:info>
</x-form.label>
<x-form.input name="username" value="{{ $user->username }}" />
</div>
@endif
<div class="flex flex-col gap-y-1">
<x-form.label for="motto">
{{ __('Motto') }}
<x-slot:info>
{{ __('Spice up your profile with a nice motto') }}
</x-slot:info>
</x-form.label>
<x-form.input name="motto" value="{{ $user->motto }}" />
</div>
@if (setting('google_recaptcha_enabled'))
<div class="g-recaptcha" data-sitekey="{{ config('habbo.site.recaptcha_site_key') }}"></div>
@endif
@if (setting('cloudflare_turnstile_enabled'))
<x-turnstile />
@endif
<div class="flex w-full justify-start md:justify-end">
<x-form.secondary-button classes="lg:w-1/4">
{{ __('Update settings') }}
</x-form.secondary-button>
</div>
</form>
</x-content.content-card>
</div>
</x-app-layout>
@@ -0,0 +1,74 @@
<x-app-layout>
@push('title', __('Password settings'))
<div class="col-span-12 flex flex-col gap-y-3 md:col-span-3">
<x-user.settings.settings-navigation />
</div>
<div class="col-span-12 flex flex-col gap-y-3 md:col-span-9">
<x-content.content-card icon="hotel-icon" classes="border dark:border-gray-900">
<x-slot:title>
{{ __('Password settings') }}
</x-slot:title>
<x-slot:under-title>
{{ __('Change your password by filling out the fields below') }}
</x-slot:under-title>
<form action="{{ route('settings.password.update') }}" method="POST" class="flex flex-col gap-y-4">
@method('PUT')
@csrf
<div class="flex flex-col gap-y-1">
<x-form.label for="current_password">
{{ __('Current password') }}
<x-slot:info>
{{ __('Enter your current password') }}
</x-slot:info>
</x-form.label>
<x-form.input name="current_password" type="password" :autofocus="true" />
</div>
<div class="flex flex-col gap-y-1">
<x-form.label for="password">
{{ __('New password') }}
<x-slot:info>
{{ __('Enter a new secure password. Do not forget to save it somewhere safe') }}
</x-slot:info>
</x-form.label>
<x-form.input name="password" type="password" />
</div>
<div class="flex flex-col gap-y-1">
<x-form.label for="password_confirmation">
{{ __('Confirm new password') }}
<x-slot:info>
{{ __('Please confirm your new password') }}
</x-slot:info>
</x-form.label>
<x-form.input name="password_confirmation" type="password" />
</div>
@if (setting('google_recaptcha_enabled'))
<div class="g-recaptcha" data-sitekey="{{ config('habbo.site.recaptcha_site_key') }}"></div>
@endif
@if (setting('cloudflare_turnstile_enabled'))
<x-turnstile />
@endif
<div class="flex w-full justify-start md:justify-end">
<x-form.secondary-button classes="lg:w-1/4">
{{ __('Update password') }}
</x-form.secondary-button>
</div>
</form>
</x-content.content-card>
</div>
</x-app-layout>
@@ -0,0 +1,72 @@
<x-app-layout>
@push('title', __('Session logs'))
<div class="col-span-12 flex flex-col gap-y-3 md:col-span-3">
<x-user.settings.settings-navigation />
</div>
<div class="col-span-12 flex flex-col gap-y-3 md:col-span-9">
<x-content.content-card icon="hotel-icon" classes="border dark:border-gray-900">
<x-slot:title>
{{ __('Session logs') }}
</x-slot:title>
<x-slot:under-title>
{{ __('Keep an eye on all your active sessions') }}
</x-slot:under-title>
<div class="overflow-hidden overflow-x-auto rounded border border-gray-200 dark:border-gray-700">
<table class="min-w-full text-sm divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-100 dark:bg-gray-800">
<tr>
<th class="whitespace-nowrap px-4 py-2 text-left font-medium text-gray-900 dark:text-white">
{{ __('IP') }}
</th>
<th class="whitespace-nowrap px-4 py-2 text-left font-medium text-gray-900 dark:text-white">
{{ __('IP Current Device') }}
</th>
<th class="whitespace-nowrap px-4 py-2 text-left font-medium text-gray-900 dark:text-white">
{{ __('Is Desktop') }}
</th>
<th class="whitespace-nowrap px-4 py-2 text-left font-medium text-gray-900 dark:text-white">
{{ __('Platform') }}
</th>
<th class="whitespace-nowrap px-4 py-2 text-left font-medium text-gray-900 dark:text-white">
{{ __('Browser') }}
</th>
<th class="whitespace-nowrap px-4 py-2 text-left font-medium text-gray-900 dark:text-white">
{{ __('Last Activity') }}
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
@forelse ($logs as $log)
<tr>
<td class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-gray-300">
{{ $log->ip_address }}
</td>
<td class="px-4 py-2 text-gray-700 dark:text-gray-300">
{{ $log->is_current_device ? 'true' : 'false' }}</td>
<td class="px-4 py-2 text-gray-700 dark:text-gray-300">
{{ $log->agent['is_desktop'] ? 'true' : 'false' }}</td>
<td class="px-4 py-2 text-gray-700 dark:text-gray-300">{{ $log->agent['platform'] }}
</td>
<td class="px-4 py-2 text-gray-700 dark:text-gray-300">{{ $log->agent['browser'] }}</td>
<td class="whitespace-nowrap px-4 py-2 text-gray-700 dark:text-gray-300">
{{ $log->last_active }}</td>
</tr>
@empty
<tr>
<td class="whitespace-nowrap px-4 py-2 text-center text-gray-700 dark:text-gray-300"
colspan="3">
{{ __('No session logs found') }}
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</x-content.content-card>
</div>
</x-app-layout>
@@ -0,0 +1,107 @@
<x-app-layout>
@push('title', __('Two factor'))
<div class="col-span-12 flex flex-col gap-y-3 md:col-span-3">
<x-user.settings.settings-navigation />
</div>
<div class="col-span-12 flex flex-col gap-y-3 md:col-span-9">
<x-content.content-card icon="hotel-icon" classes="border dark:border-gray-900">
<x-slot:title>
{{ __('Two factor authentication') }}
</x-slot:title>
<x-slot:under-title>
{{ __('Add an extra layer of security to your account by enabling two-factor authentication') }}
</x-slot:under-title>
<!-- 2FA enabled, we display the QR code : -->
@if (auth()->user()->two_factor_confirmed)
<form action="{{ route('user.two-factor.disable') }}" method="post">
@csrf
@method('delete')
<x-form.danger-button>
{{ __('Disable 2FA') }}
</x-form.danger-button>
</form>
{{-- 2FA enabled but not yet confirmed, we show the QRcode and ask for confirmation --}}
@elseif(auth()->user()->two_factor_secret)
<p>{{ __('Validate your two-factor enabling by scanning the following QR-code and enter your auto-generated 2-factor code from your phone.') }}
</p>
<div class="mt-4 flex flex-col items-center md:flex-row md:items-start md:justify-center">
<div class="flex gap-x-8 rounded bg-gray-100 px-4 py-2">
<span class="flex items-center">
{!! auth()->user()->twoFactorQrCodeSvg() !!}
</span>
<div>
<strong>
{{ __('Recovery codes:') }}
</strong>
<ul>
@foreach (auth()->user()->recoveryCodes() as $code)
<li>{{ $code }}</li>
@endforeach
</ul>
</div>
</div>
</div>
<div class="mt-2 flex justify-center text-xs italic text-gray-600">
<div class="w-full lg:w-[480px]">
{{ __('Please save your recovery codes somewhere safe! If you lose access to your 2FA codes, those recovery codes will be needed to regain access your account.') }}
</div>
</div>
<form action="{{ route('two-factor.verify') }}" method="POST" class="mt-8">
@csrf
<x-form.label for="code">
{{ __('Code') }}
<x-slot:info>
{{ __('Please scan the QR-code above with your phone to retrieve your two-factor authentication code.') }}
</x-slot:info>
</x-form.label>
<x-form.input classes="mb-3" name="code" placeholder="{{ __('Code') }}" />
@if (setting('google_recaptcha_enabled'))
<div class="g-recaptcha" data-sitekey="{{ config('habbo.site.recaptcha_site_key') }}"></div>
@endif
@if (setting('cloudflare_turnstile_enabled'))
<x-turnstile />
@endif
<x-form.secondary-button classes="mt-4">
{{ __('Verify 2FA') }}
</x-form.secondary-button>
</form>
@else
<div class="flex flex-col items-end">
<div class="flex w-full flex-col gap-y-3 dark:text-gray-100">
<p>
{{ __('Here at :hotel we take security very serious and therefore we offer you as a user a way to secure your beloved account even further, by allowing you to enable Googles 2-factor authentication!', ['hotel' => setting('hotel_name')]) }}
</p>
<p>
{{ __('2-factor authentication adds an extra layer of security to your account, making it physical impossible to access it without having access to your mobile phone as only your phone will contain the 2-factor authentication code which will be re-generated every 30 seconds automatically') }}
</p>
</div>
<form action="{{ route('user.two-factor.enable') }}" method="post" class="mt-8">
@csrf
<x-form.secondary-button>
{{ __('Activate 2FA') }}
</x-form.secondary-button>
</form>
</div>
@endif
</x-content.content-card>
</div>
</x-app-layout>