Added Tour Navigator
This commit is contained in:
@@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class Tour extends Model
|
||||
{
|
||||
protected $fillable = ['name', 'internal_name', 'short_description'];
|
||||
protected $fillable = ['name', 'internal_name', 'short_description', 'long_description',];
|
||||
public $timestamps = false;
|
||||
|
||||
public function countries()
|
||||
|
||||
@@ -16,6 +16,7 @@ return new class extends Migration
|
||||
$table->string('name');
|
||||
$table->string('internal_name');
|
||||
$table->string('short_description');
|
||||
$table->string('long_description');;
|
||||
$table->integer('length');
|
||||
$table->integer('price');
|
||||
$table->string('level');
|
||||
|
||||
@@ -13,9 +13,9 @@ class TourSeeder extends Seeder
|
||||
public function run(): void
|
||||
{
|
||||
\DB::table('tours')->insert([
|
||||
['length' => 8, 'name' => "Cantonese Charm", 'short_description' => "Guangdong is known for it's big, global cities, but there is so much more to discover; including pristine natural beauty.", 'internal_name' => "cantonese_charm", 'level' => "Beginner", 'price' => 1000],
|
||||
['length' => 7, 'name' => "Fujianese Fantasy", 'short_description' => "Experience fresh seafood in Xiamen, and then move rurally for an authentic dive into Hakka culture", 'internal_name' => "fujianese_fantasy", 'level' => "Beginner", 'price' => 1200],
|
||||
['length' => 10, 'name' => "Hebei Harmony", 'short_description' => "The Great Wall, Great Food and ancient treasures in one of China's most underrated provinces.", 'internal_name' => "hebei_harmony", 'level' => "Moderate", 'price' => 1500],
|
||||
['length' => 8, 'name' => "Cantonese Charm", 'long_description' => 'Hebei is cool', 'short_description' => "Guangdong is known for it's big, global cities, but there is so much more to discover; including pristine natural beauty.", 'internal_name' => "cantonese_charm", 'level' => "Beginner", 'price' => 1000],
|
||||
['length' => 7, 'name' => "Fujianese Fantasy", 'long_description' => 'Hebei is cool', 'short_description' => "Experience fresh seafood in Xiamen, and then move rurally for an authentic dive into Hakka culture", 'internal_name' => "fujianese_fantasy", 'level' => "Beginner", 'price' => 1200],
|
||||
['length' => 10, 'name' => "Hebei Harmony", 'long_description' => 'Hebei is cool', 'short_description' => "The Great Wall, Great Food and ancient treasures in one of China's most underrated provinces.", 'internal_name' => "hebei_harmony", 'level' => "Moderate", 'price' => 1500],
|
||||
]);
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<article class="tour-actions">
|
||||
<EdgyButton v-if="!tourDay" classes="btn-primary chamfer">
|
||||
<ButtonLink :href="'/adventures/'+(tour.internal_name)+'/day/1'">
|
||||
Explore Itinerary
|
||||
</ButtonLink>
|
||||
</EdgyButton>
|
||||
<EdgyButton v-if="tourDay" classes="btn-secondary chamfer">
|
||||
<ButtonLink href="#">
|
||||
Previous Day
|
||||
</ButtonLink>
|
||||
</EdgyButton>
|
||||
<EdgyButton v-if="tourDay" classes="btn-primary chamfer">
|
||||
<ButtonLink href="#">
|
||||
Next Day
|
||||
</ButtonLink>
|
||||
</EdgyButton>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import EdgyButton from "@/components/dredgy/EdgyButton.vue";
|
||||
import type {Tour, TourDay} from "@/types";
|
||||
import ButtonLink from "@/components/dredgy/ButtonLink.vue";
|
||||
|
||||
interface Props {
|
||||
tourDay?: TourDay;
|
||||
tour: Tour;
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tour-actions {
|
||||
display: flex;
|
||||
gap: 2em;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
flex-basis: 10%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<aside class="tour-aside chamfer" v-show-on-intersect="{type:'fade-up'}">
|
||||
<div class="tour-aside chamfer" v-show-on-intersect="{type:'fade-up'}">
|
||||
<h3 class="aside-title">Quick Facts</h3>
|
||||
<ul class="facts">
|
||||
<li v-if="tour.tour_days?.length > 0">
|
||||
@@ -11,24 +11,28 @@
|
||||
<span class="value">{{ tour.level }}</span>
|
||||
</li>
|
||||
<li v-if="true">
|
||||
<span class="label">Price</span>
|
||||
<span class="value">{{ Intl.NumberFormat(undefined, { style: 'currency', currency: 'USD' }).format(tour.price) }}</span>
|
||||
<span class="label">Price From</span>
|
||||
<span class="value">{{
|
||||
Intl.NumberFormat(undefined, {
|
||||
style: 'currency',
|
||||
currency: 'USD'
|
||||
}).format(tour.price)
|
||||
}}</span>
|
||||
</li>
|
||||
<li v-if="tour.min_people || tour.max_people">
|
||||
<span class="label">Group Size</span>
|
||||
<span class="value">
|
||||
{{ tour.min_people ?? '?' }}–{{ tour.max_people ?? '?' }} people
|
||||
</span>
|
||||
<span class="value">{{ tour.min_people ?? '?' }}–{{ tour.max_people ?? '?' }} people</span>
|
||||
</li>
|
||||
<li v-if="Array.isArray(tour.countries) && tour.countries.length">
|
||||
<span class="label">Countries</span>
|
||||
<span class="value">
|
||||
{{ tour.countries?.map((c:any)=>c.name ?? c).join(', ') }}
|
||||
</span>
|
||||
<span class="value">{{ tour.countries?.map((c: any) => c.name ?? c).join(', ') }}</span>
|
||||
</li>
|
||||
<li class="departures-item">
|
||||
<span class="label">Departures</span>
|
||||
<span class="value">No Upcoming Departures</span>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="aside-title">Upcoming Departures</h3>
|
||||
</aside>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -44,8 +48,10 @@ defineProps<{ tour: Tour }>();
|
||||
color: var(--foreground);
|
||||
border: 1px solid color-mix(in oklab, var(--foreground), transparent 85%);
|
||||
padding: 1.25rem;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.aside-title {
|
||||
margin: 1rem 0 1rem 0;
|
||||
font-size: 1rem;
|
||||
@@ -53,6 +59,7 @@ defineProps<{ tour: Tour }>();
|
||||
letter-spacing: 0.02em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.facts {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
@@ -60,6 +67,7 @@ defineProps<{ tour: Tour }>();
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.facts li {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
@@ -67,11 +75,85 @@ defineProps<{ tour: Tour }>();
|
||||
padding: 0.5rem 0.25rem;
|
||||
border-bottom: 1px dashed color-mix(in oklab, var(--foreground), transparent 90%);
|
||||
}
|
||||
|
||||
.facts .label {
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
.facts .value {
|
||||
color: var(--foreground);
|
||||
font-weight: 600;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Mobile responsive */
|
||||
@media (max-width: 1023px) {
|
||||
.tour-aside {
|
||||
padding: 2em 0.75em 0 2em;
|
||||
}
|
||||
|
||||
.aside-title {
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.aside-title:not(:first-of-type) {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.facts {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.facts li {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.125rem;
|
||||
padding: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.departures-item {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
|
||||
.facts .label {
|
||||
font-size: 0.65rem;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.facts .value {
|
||||
font-size: 0.8rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.aside-title:first-of-type {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.aside-title:first-of-type {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.facts {
|
||||
grid-template-columns: 1fr auto;
|
||||
}
|
||||
|
||||
.facts li {
|
||||
display: grid;
|
||||
grid-template-columns: auto;
|
||||
border-bottom: 1px dashed color-mix(in oklab, var(--foreground), transparent 90%);
|
||||
padding: 0.5rem 0.25rem;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,7 +7,7 @@ defineProps({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Link :href="href" style="display:block;width:100%;height:100%" >
|
||||
<Link :href="href || '#'" style="display:block;width:100%;height:100%" >
|
||||
<slot/>
|
||||
</Link>
|
||||
</template>
|
||||
|
||||
@@ -145,7 +145,10 @@ main{
|
||||
display: flex; /* added */
|
||||
flex-direction: column; /* keep */
|
||||
flex: 1;
|
||||
gap: 2em;/* keep */
|
||||
}
|
||||
|
||||
main:not(:has(.no-gap)) {
|
||||
gap: 2em;
|
||||
}
|
||||
|
||||
/* Push the Footer (last child in main) to the bottom if content is short */
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
import { usePage } from "@inertiajs/vue3";
|
||||
import AppLayout from "@/layouts/AppLayout.vue";
|
||||
import TourOverviewSection from "./TourOverviewSection.vue";
|
||||
import type { Tour } from "@/types";
|
||||
import type {Tour, TourDay} from "@/types";
|
||||
import TourQuickFacts from "@/components/TourNavigator/TourQuickFacts.vue";
|
||||
import SectionTitle from "@/components/dredgy/SectionTitle.vue";
|
||||
|
||||
interface Properties {
|
||||
tour: Tour;
|
||||
nextHref?: string | null;
|
||||
tourDay: TourDay
|
||||
}
|
||||
|
||||
const { tour, nextHref } = usePage().props as unknown as Properties;
|
||||
const { tour, tourDay} = usePage().props as unknown as Properties;
|
||||
|
||||
defineOptions({
|
||||
layout: AppLayout,
|
||||
@@ -19,18 +19,8 @@ defineOptions({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="tour-overview-section">
|
||||
<SectionTitle
|
||||
title=""
|
||||
:gradient="tour.name"
|
||||
:subtitle="tour.short_description ?? ''"
|
||||
/>
|
||||
</section>
|
||||
<TourOverviewSection :tour="tour" />
|
||||
<TourOverviewSection :tourDay="tourDay" :tour="tour" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.tour-overview-section{
|
||||
margin-top: 10dvh;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,76 +1,202 @@
|
||||
<script setup lang="ts">
|
||||
import SectionContainer from "@/components/dredgy/SectionContainer.vue";
|
||||
import SectionTitle from "@/components/dredgy/SectionTitle.vue";
|
||||
import GradientText from "@/components/dredgy/GradientText.vue";
|
||||
import EdgyButton from "@/components/dredgy/EdgyButton.vue";
|
||||
import ButtonLink from "@/components/dredgy/ButtonLink.vue";
|
||||
import TourQuickFacts from "@/components/TourNavigator/TourQuickFacts.vue";
|
||||
import type { Tour } from "@/types";
|
||||
import TourOverviewActions from "@/components/TourNavigator/TourOverviewActions.vue";
|
||||
import type {Tour, TourDay} from "@/types";
|
||||
import {ref} from "vue";
|
||||
|
||||
interface Props {
|
||||
tour: Tour;
|
||||
tourDay?: TourDay;
|
||||
}
|
||||
|
||||
const currentStep = ref(1)
|
||||
const props = defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="tour-overview">
|
||||
<SectionContainer>
|
||||
<section v-show-on-intersect class="no-gap tour-overview chamfer-tl">
|
||||
<div
|
||||
class="relative chamfer bg-neutral-900/70 border border-neutral-700/60 shadow-xl shadow-black/30 backdrop-blur-sm"
|
||||
:style="{ backgroundImage: `url('/img/tours/${tour.internal_name}.jpg')` }"
|
||||
style="background-attachment: scroll; background-size: cover; background-position: center"
|
||||
class="tour-overview-header"
|
||||
>
|
||||
<!-- Banner with overlapping title -->
|
||||
<div class="relative">
|
||||
<div class="aspect-[16/7] md:aspect-[16/6] lg:aspect-[16/5] overflow-hidden">
|
||||
<img
|
||||
:src="`/img/tours/${props.tour.internal_name}.jpg`"
|
||||
:alt="tour.name + 'Banner'"
|
||||
class="w-full h-full object-cover"
|
||||
loading="lazy"
|
||||
<h1 class="glass chamfer">
|
||||
<GradientText>{{ tour.name }}</GradientText>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="tour-overview-body">
|
||||
<section class="tour-content">
|
||||
<article class="tour-description">
|
||||
<div v-if="tour.tour_days?.length" class="custom-stepper">
|
||||
<!-- Horizontal Stepper Header -->
|
||||
<div class="stepper-header">
|
||||
<button
|
||||
v-for="(day, index) in tour.tour_days"
|
||||
:key="day.id"
|
||||
class="stepper-step"
|
||||
:class="{
|
||||
active: currentStep === index + 1,
|
||||
complete: currentStep > index + 1
|
||||
}"
|
||||
@click="currentStep = index + 1"
|
||||
>
|
||||
<span class="step-number">Day {{ index + 1 }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Stepper Content -->
|
||||
<div class="stepper-content">
|
||||
<div
|
||||
v-for="(day, index) in tour.tour_days"
|
||||
:key="day.id"
|
||||
v-show="currentStep === index + 1"
|
||||
class="step-item"
|
||||
>
|
||||
<h2 class="text-h3 font-weight-bold mb-2">
|
||||
Day {{ index + 1 }}
|
||||
</h2>
|
||||
<p class="text-h6 text-grey mb-6">
|
||||
{{ day.description }}
|
||||
</p>
|
||||
|
||||
<div v-if="day.image" class="mb-6">
|
||||
<v-img
|
||||
:src="day.image"
|
||||
:alt="`Day ${index + 1}`"
|
||||
class="rounded"
|
||||
height="300"
|
||||
cover
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Overlapping H1 with glass background (no rounded, chamfered) -->
|
||||
<div class="absolute left-6 md:left-8 -bottom-8">
|
||||
<div
|
||||
class="chamfer border border-white/10 glass shadow-lg shadow-black/30 px-4 md:px-5 py-2.5"
|
||||
>
|
||||
<h1 style="padding:0.5em" class="text-2xl md:text-3xl lg:text-4xl font-semibold tracking-tight">
|
||||
<GradientText>About this Adventure</GradientText>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-body1 line-height-relaxed mb-6">
|
||||
{{ day.content }}
|
||||
</div>
|
||||
|
||||
<!-- Content area: flex columns, fixed height, right column flush with edge -->
|
||||
<div>
|
||||
<div class="flex gap-6 h-[560px] md:h-[600px] lg:h-[640px]">
|
||||
<!-- Main description (wider column) -->
|
||||
<div class="flex-1 pl-6 md:pl-8">
|
||||
<div class="text-neutral-200 leading-relaxed h-full overflow-auto pr-1 pt-14 ">
|
||||
<div
|
||||
v-html="props.tour.long_description || 'No long description available'"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick facts (narrower right column, flush right, chamfer top-left only) -->
|
||||
<aside class="w-80 md:w-88 lg:w-96 h-full">
|
||||
<div
|
||||
class="h-full chamfer-tl bg-neutral-900/40 backdrop-blur-sm ring-1 ring-neutral-700/50"
|
||||
<div class="d-flex gap-3">
|
||||
<v-btn
|
||||
v-if="index > 0"
|
||||
variant="outlined"
|
||||
@click="currentStep = index"
|
||||
>
|
||||
<TourQuickFacts :tour="props.tour" />
|
||||
Previous
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-if="index < tour.tour_days.length - 1"
|
||||
color="primary"
|
||||
@click="currentStep = index + 2"
|
||||
>
|
||||
Next
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-else
|
||||
color="success"
|
||||
disabled
|
||||
>
|
||||
Tour Complete
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
<aside class="chamfer chamfer-tl">
|
||||
<TourQuickFacts :tour="tour" />
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SectionContainer>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.tour-overview {
|
||||
margin: 5%;
|
||||
background: var(--sidebar-background);
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
min-height: 70vh;
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tour-overview-header {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.tour-overview-header h1 {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
transform: translateY(50%) translateX(-50%);
|
||||
left: 37.5%;
|
||||
padding: 0.2em 0.75em;
|
||||
text-align: center;
|
||||
font-size: 2.5em;
|
||||
margin: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.tour-overview-body {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.tour-overview-body .tour-content {
|
||||
flex: 1;
|
||||
padding: 2em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.tour-description {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tour-overview-body aside {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-basis: 25%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.tour-overview {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.tour-overview-header h1 {
|
||||
font-size: 1.5em;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.tour-overview-body {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.tour-overview-body aside {
|
||||
order: 1;
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.tour-overview-body .tour-content {
|
||||
padding-top: 0.5em;
|
||||
order: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.chamfer {
|
||||
--cut: 20px;
|
||||
clip-path: polygon(
|
||||
@@ -83,7 +209,6 @@ const props = defineProps<Props>();
|
||||
);
|
||||
}
|
||||
|
||||
/* Only the top-left corner chamfered (for the right column box) */
|
||||
.chamfer-tl {
|
||||
--cut: 20px;
|
||||
clip-path: polygon(
|
||||
@@ -94,4 +219,82 @@ const props = defineProps<Props>();
|
||||
0 0
|
||||
);
|
||||
}
|
||||
|
||||
.line-height-relaxed {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.custom-stepper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.stepper-header {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
overflow-x: auto;
|
||||
padding: 1rem 0;
|
||||
border-bottom: 2px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.stepper-step {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: transparent;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.stepper-step:hover {
|
||||
border-color: rgba(255, 255, 255, 0.6);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.stepper-step.active {
|
||||
border-color: #1976d2;
|
||||
background-color: rgba(25, 118, 210, 0.1);
|
||||
color: #1976d2;
|
||||
}
|
||||
|
||||
.stepper-step.complete {
|
||||
border-color: #4caf50;
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.step-label {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.stepper-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.step-item {
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user