feat: add landing page components including FAQ, features, footer, header, hero, modalities, steps, and section title
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
@keyframes landing-float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-12px); }
|
||||
}
|
||||
|
||||
@keyframes landing-scan {
|
||||
0% { top: 0; opacity: 0; }
|
||||
8% { opacity: 1; }
|
||||
92% { opacity: 1; }
|
||||
100% { top: 100%; opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes landing-pulse {
|
||||
0% { transform: scale(0.9); opacity: 0.8; }
|
||||
100% { transform: scale(1.7); opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes landing-blob {
|
||||
0%, 100% { border-radius: 42% 58% 60% 40% / 45% 40% 60% 55%; }
|
||||
50% { border-radius: 58% 42% 40% 60% / 55% 60% 40% 45%; }
|
||||
}
|
||||
|
||||
@keyframes landing-kenburns {
|
||||
from { transform: scale(1); }
|
||||
to { transform: scale(1.08); }
|
||||
}
|
||||
|
||||
@keyframes landing-spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes landing-marquee {
|
||||
from { transform: translateX(0); }
|
||||
to { transform: translateX(50%); }
|
||||
}
|
||||
|
||||
@keyframes landing-draw {
|
||||
to { stroke-dashoffset: 0; }
|
||||
}
|
||||
|
||||
@keyframes landing-timeline {
|
||||
0%, 12% { opacity: 0.35; }
|
||||
18%, 100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes landing-toggle {
|
||||
0%, 40% { transform: translateX(0); }
|
||||
50%, 90% { transform: translateX(-100%); }
|
||||
100% { transform: translateX(0); }
|
||||
}
|
||||
|
||||
@keyframes landing-bubble {
|
||||
0% { opacity: 0; transform: translateY(12px) scale(0.96); }
|
||||
100% { opacity: 1; transform: translateY(0) scale(1); }
|
||||
}
|
||||
|
||||
.landing-page {
|
||||
background-image: radial-gradient(rgba(128, 14, 19, 0.08) 1px, transparent 1px);
|
||||
background-size: 28px 28px;
|
||||
}
|
||||
|
||||
.landing-grid {
|
||||
background-image: linear-gradient(#DEE3EB 1px, transparent 1px), linear-gradient(90deg, #DEE3EB 1px, transparent 1px);
|
||||
background-size: 32px 32px;
|
||||
}
|
||||
|
||||
.landing-float {
|
||||
animation: landing-float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.landing-float--delay {
|
||||
animation-delay: 1.6s;
|
||||
}
|
||||
|
||||
.landing-scan {
|
||||
animation: landing-scan 3.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.landing-pulse::after {
|
||||
content: '';
|
||||
@apply absolute inset-0 rounded-full border-2 border-complement-700;
|
||||
animation: landing-pulse 2.2s ease-out infinite;
|
||||
}
|
||||
|
||||
.landing-blob {
|
||||
animation: landing-blob 14s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.landing-kenburns {
|
||||
animation: landing-kenburns 24s ease-out forwards;
|
||||
}
|
||||
|
||||
.landing-spin svg {
|
||||
animation: landing-spin 18s linear infinite;
|
||||
}
|
||||
|
||||
.landing-marquee {
|
||||
animation: landing-marquee 32s linear infinite;
|
||||
}
|
||||
|
||||
.landing-marquee:hover {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
.landing-underline path {
|
||||
stroke-dasharray: 320;
|
||||
stroke-dashoffset: 320;
|
||||
animation: landing-draw 1.1s ease-out 0.5s forwards;
|
||||
}
|
||||
|
||||
.landing-timeline-step {
|
||||
animation: landing-timeline 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.landing-timeline-step:nth-child(2) { animation-delay: 1.6s; }
|
||||
.landing-timeline-step:nth-child(3) { animation-delay: 3.2s; }
|
||||
.landing-timeline-step:nth-child(4) { animation-delay: 4.8s; }
|
||||
|
||||
.landing-toggle-thumb {
|
||||
animation: landing-toggle 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.landing-bubble {
|
||||
opacity: 0;
|
||||
animation: landing-bubble 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
.landing-bubble:nth-child(2) { animation-delay: 0.6s; }
|
||||
.landing-bubble:nth-child(3) { animation-delay: 1.2s; }
|
||||
|
||||
.landing-reveal {
|
||||
@apply opacity-0 translate-y-8 transition-all duration-700 ease-out;
|
||||
}
|
||||
|
||||
.landing-reveal.is-visible {
|
||||
@apply opacity-100 translate-y-0;
|
||||
}
|
||||
|
||||
.landing-reveal--1 { transition-delay: 100ms; }
|
||||
.landing-reveal--2 { transition-delay: 200ms; }
|
||||
.landing-reveal--3 { transition-delay: 300ms; }
|
||||
.landing-reveal--4 { transition-delay: 400ms; }
|
||||
.landing-reveal--5 { transition-delay: 500ms; }
|
||||
|
||||
.landing-timeline-line {
|
||||
@apply origin-top scale-y-0 transition-transform duration-1000 ease-out;
|
||||
}
|
||||
|
||||
.landing-reveal.is-visible .landing-timeline-line {
|
||||
@apply scale-y-100;
|
||||
}
|
||||
|
||||
.landing-faq summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.landing-faq[open] .landing-faq-icon {
|
||||
@apply rotate-45;
|
||||
}
|
||||
|
||||
html:has(.landing-page) {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.landing-float,
|
||||
.landing-scan,
|
||||
.landing-kenburns,
|
||||
.landing-spin svg,
|
||||
.landing-blob,
|
||||
.landing-marquee,
|
||||
.landing-timeline-step,
|
||||
.landing-toggle-thumb,
|
||||
.landing-pulse::after {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.landing-underline path {
|
||||
animation: none;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
|
||||
.landing-bubble {
|
||||
animation: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.landing-reveal {
|
||||
@apply opacity-100 translate-y-0 transition-none;
|
||||
}
|
||||
|
||||
.landing-timeline-line {
|
||||
@apply scale-y-100 transition-none;
|
||||
}
|
||||
}
|
||||
@@ -23,19 +23,19 @@
|
||||
}
|
||||
|
||||
.ui-button--dominant.p-button.p-button-outlined {
|
||||
@apply bg-transparent text-dominant-500 border-dominant-500;
|
||||
@apply !bg-transparent !text-dominant-500 border-dominant-500;
|
||||
}
|
||||
|
||||
.ui-button--dominant.p-button.p-button-outlined:hover {
|
||||
@apply bg-dominant-500 text-white;
|
||||
@apply !bg-dominant-500 !text-white;
|
||||
}
|
||||
|
||||
.ui-button--dominant.p-button.p-button-text {
|
||||
@apply bg-transparent text-dominant-500 border-transparent;
|
||||
@apply !bg-transparent !text-dominant-500 !border-transparent;
|
||||
}
|
||||
|
||||
.ui-button--dominant.p-button.p-button-text:hover {
|
||||
background-color: rgba(128, 14, 19, 0.1);
|
||||
background-color: rgba(128, 14, 19, 0.1) !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -81,3 +81,10 @@
|
||||
background: #576989 !important;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.fast-request-dialog {
|
||||
width: calc(100vw - 1.5rem) !important;
|
||||
max-width: 688px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,3 +48,13 @@
|
||||
.p-datatable-tbody > tr > td{
|
||||
@apply !border-0
|
||||
}
|
||||
|
||||
.table-generic {
|
||||
@apply w-full min-w-0;
|
||||
}
|
||||
.table-generic-scroll {
|
||||
@apply w-full overflow-x-auto;
|
||||
}
|
||||
.table-generic-scroll .p-datatable-table {
|
||||
@apply min-w-full;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
@import "tailwindcss";
|
||||
@import "./Client/sidebar/sidebar.css";
|
||||
@import "./Client/page-transitions.css";
|
||||
@import "./Client/landing.css";
|
||||
@config "../../Client-tailwind.config.js";
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ defineProps({
|
||||
<ActivitiesWidget :stats="stats" />
|
||||
<UiCard title="ثبت آنی درخواست جدید" variant="default" class="mt-4">
|
||||
<p class="w-full flex items-center justify-start font-[400] text-[11px]">فقط چند قدم ساده برای ثبت درخواست کافیه.</p>
|
||||
<div class="w-full h-[179px] grid grid-cols-5 gap-3 justify-start pt-[10px]">
|
||||
<div class="w-full grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 justify-start pt-[10px]">
|
||||
<RequestCard
|
||||
v-for="modality in modalities"
|
||||
:key="modality.code"
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
<script setup>
|
||||
import { Link } from '@inertiajs/inertia-vue3'
|
||||
import { ref } from 'vue'
|
||||
import { usePage } from '@inertiajs/inertia-vue3'
|
||||
import { useScrollReveal } from '../composables/useScrollReveal'
|
||||
import LandingHeader from '../components/landing/LandingHeader.vue'
|
||||
import LandingHero from '../components/landing/LandingHero.vue'
|
||||
import LandingMarquee from '../components/landing/LandingMarquee.vue'
|
||||
import LandingSteps from '../components/landing/LandingSteps.vue'
|
||||
import LandingFeatures from '../components/landing/LandingFeatures.vue'
|
||||
import LandingModalities from '../components/landing/LandingModalities.vue'
|
||||
import LandingComparison from '../components/landing/LandingComparison.vue'
|
||||
import LandingFaq from '../components/landing/LandingFaq.vue'
|
||||
import LandingCta from '../components/landing/LandingCta.vue'
|
||||
import LandingFooter from '../components/landing/LandingFooter.vue'
|
||||
|
||||
const {url ,props} = usePage();
|
||||
const user = props.value.auth.User || null;
|
||||
const { props } = usePage()
|
||||
const user = props.value.auth.User || null
|
||||
|
||||
const page = ref(null)
|
||||
|
||||
useScrollReveal(page)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-screen flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-2xl w-full space-y-8">
|
||||
<h1 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
|
||||
پروژه رادیکال
|
||||
</h1>
|
||||
<div ref="page" class="landing-page min-h-screen bg-white text-dark">
|
||||
<LandingHeader :user="user" />
|
||||
|
||||
<div class="bg-white p-6 rounded-lg space-y-6">
|
||||
<p>
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی و فرهنگ پیشرو در زبان فارسی ایجاد کرد. در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.
|
||||
</p>
|
||||
</div>
|
||||
<main>
|
||||
<LandingHero :user="user" />
|
||||
<LandingMarquee />
|
||||
<LandingSteps />
|
||||
<LandingFeatures />
|
||||
<LandingModalities />
|
||||
<LandingComparison />
|
||||
<LandingFaq />
|
||||
<LandingCta :user="user" />
|
||||
</main>
|
||||
|
||||
<div class="flex items-center justify-center gap-4" v-if="!user">
|
||||
<Link :href="route('login')" class="text-center bg-primary text-white px-4 py-2 rounded-md hover:bg-primary-active transition-all duration-300">
|
||||
ورود
|
||||
</Link>
|
||||
<Link :href="route('login')" class="text-center bg-primary text-white px-4 py-2 rounded-md hover:bg-primary-active transition-all duration-300">
|
||||
ثبت نام
|
||||
</Link>
|
||||
</div>
|
||||
<div class="flex items-center justify-center gap-4" v-if="user">
|
||||
<a :href="route('dashboard.index')" class="text-center bg-primary text-white px-4 py-2 rounded-md hover:bg-primary-active transition-all duration-300">
|
||||
داشبورد
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<LandingFooter />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -65,9 +65,9 @@
|
||||
props.selectable && 'cursor-pointer',
|
||||
fastRequestStore.requestType === props.value ? 'border-[#576989] border-2': 'border-[#DEE3EB]'
|
||||
]">
|
||||
<component :is="iconComponent" class="w-[87px] h-[80px]" />
|
||||
<component :is="iconComponent" class="w-[72px] h-[66px] sm:w-[87px] sm:h-[80px] shrink-0" />
|
||||
<div class="w-full flex flex-col gap-1">
|
||||
<p class="w-full flex items-center justify-center font-[700] text-[14px]">{{ title }}</p>
|
||||
<p class="w-full flex items-center justify-center text-center font-[700] text-[13px] sm:text-[14px] leading-6">{{ title }}</p>
|
||||
<ui-button v-if="!selectable" @click="submitRequest" label="ثبت درخواست" severity="secondary" size="small" full-width="true"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -32,7 +32,7 @@ const showChooseArchive = () => {
|
||||
</p>
|
||||
<button type="button" @click="fastRequestStore.clearArchivePet" class="text-[11px] font-[400] text-[#7A1419] cursor-pointer">حذف و ثبت کیس جدید</button>
|
||||
</div>
|
||||
<form v-else class="p-4 grid grid-cols-2 gap-4 w-full">
|
||||
<form v-else class="p-4 grid grid-cols-1 sm:grid-cols-2 gap-4 w-full">
|
||||
<InputText
|
||||
v-model="fastRequestStore.requestCase.name"
|
||||
type="text"
|
||||
|
||||
@@ -11,7 +11,7 @@ const fastRequestStore = useFastRequestStore();
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<p class="text-[11px] font-[400] text-[#3E4C63] py-3">جزئیات درخواست و اطلاعات مورد نیاز را با دقت و حوصله وارد نمایید.</p>
|
||||
<div class="w-full grid grid-cols-2 gap-2 items-center justify-between">
|
||||
<div class="w-full grid grid-cols-1 sm:grid-cols-2 gap-2 items-center justify-between">
|
||||
<Select
|
||||
v-model="fastRequestStore.requestDetails.priority"
|
||||
:options="priorities"
|
||||
@@ -29,7 +29,7 @@ const fastRequestStore = useFastRequestStore();
|
||||
rows="3"
|
||||
class="w-full h-full" />
|
||||
</div>
|
||||
<div class="w-full grid grid-cols-2 gap-2 items-start justify-between my-4">
|
||||
<div class="w-full grid grid-cols-1 sm:grid-cols-2 gap-2 items-start justify-between my-4">
|
||||
<FileUploadBox v-model="fastRequestStore.historyFiles" title="سوابق پزشکی قبلی (اختیاری)" />
|
||||
<FileUploadBox v-model="fastRequestStore.scanFiles" :title="`فایل «${modalityTitle(fastRequestStore.requestType)}»`" />
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ const selectDoctor = (doctorId) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full h-full grid grid-cols-3 gap-2 items-center justify-between py-4">
|
||||
<div class="w-full h-full grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2 items-center justify-between py-4">
|
||||
<button
|
||||
type="button"
|
||||
@click="selectDoctor(null)"
|
||||
@@ -17,7 +17,7 @@ const selectDoctor = (doctorId) => {
|
||||
:class="fastRequestStore.doctorId === null ? 'border-[2px] border-[#576989]' : 'border-[1px] border-[#DEE3EB]'"
|
||||
>
|
||||
<h3 class="text-[13px] font-[600] text-[#576989]">انتخاب خودکار</h3>
|
||||
<p class="w-[190px] text-center text-[11px] font-[600] text-[#3E4C63]">انتخاب در دسترس ترین پزشک جهت بررسی سریع درخواست شما</p>
|
||||
<p class="max-w-[190px] px-2 text-center text-[11px] font-[600] text-[#3E4C63]">انتخاب در دسترس ترین پزشک جهت بررسی سریع درخواست شما</p>
|
||||
</button>
|
||||
<button
|
||||
v-for="doctor in fastRequestStore.doctors"
|
||||
|
||||
@@ -6,7 +6,7 @@ import { modalities } from '../../../data/fastRequestOptions';
|
||||
<template>
|
||||
<div class="w-full space-y-3 py-6">
|
||||
<p class="h-[17px] flex items-center justify-start text-[11px] font-[600] text-[#3E4C63]">نوع درخواست خود را مشخص کنید</p>
|
||||
<div class="w-full h-[133px] grid grid-cols-5 gap-3 justify-start">
|
||||
<div class="w-full grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-3 justify-start">
|
||||
<RequestCard
|
||||
v-for="modality in modalities"
|
||||
:key="modality.code"
|
||||
|
||||
@@ -45,44 +45,38 @@ const menuItems = [
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header class="grid items-center
|
||||
shadow-client-gray/10 grid-cols-2a pe-4 justify-between !ps-[16rem] max-sm:!ps-4 fixed top-0 left-0 right-0 z-20 w-full h-[4.5rem] bg-white">
|
||||
<div class="grid grid-cols-2a justify-start items-center gap-4">
|
||||
<div class="grid grid-cols-1 max-sm:!grid-cols-2a justify-start items-center">
|
||||
<Button
|
||||
icon="fi-rr-menu-burger"
|
||||
class="!hidden !invisible !px-0 !w-0 !h-0 max-sm:!w-10 max-sm:!h-10 max-sm:!visible max-sm:!block items-center !border-dominant-50"
|
||||
pt:icon="flex !text-dominant-300 justify-center items-center"
|
||||
variant="outlined"
|
||||
size="large"
|
||||
@click="toggleSidebar"
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div class="grid grid-cols-1 h-[4rem] content-center justify-start items-center">
|
||||
<UiInput
|
||||
placeholder="جستجو سریع: نام سرپرست، نام حیوان و یا شماره پرونده"
|
||||
variant="outlined"
|
||||
prefixClasses="!border-dominant-50"
|
||||
class="!w-[30rem] max-lg:!w-[22rem] max-md:!w-[26rem] max-sm:!w-[15rem] max-xs:!w-[14rem]"
|
||||
prefixColor="dominant-700"
|
||||
iconStart="svg:SearchSvg"
|
||||
wrapperBorderClass="!border-dominant-50"
|
||||
customClass="placeholder:!text-dominant-300 !border-dominant-50 !font-normal !text-[11px]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<header class="flex items-center gap-3 sm:gap-4 shadow-client-gray/10 px-4 lg:!ps-[16rem] fixed top-0 left-0 right-0 z-20 w-full h-[4.5rem] bg-white">
|
||||
<Button
|
||||
icon="fi-rr-menu-burger"
|
||||
class="lg:!hidden !w-10 !h-10 shrink-0 !border-dominant-50"
|
||||
pt:icon="flex !text-dominant-300 justify-center items-center"
|
||||
variant="outlined"
|
||||
size="large"
|
||||
@click="toggleSidebar"
|
||||
/>
|
||||
<div class="flex-1 min-w-0 max-w-[30rem]">
|
||||
<UiInput
|
||||
placeholder="جستجو سریع: نام سرپرست، نام حیوان و یا شماره پرونده"
|
||||
variant="outlined"
|
||||
prefixClasses="!border-dominant-50"
|
||||
class="!w-full"
|
||||
prefixColor="dominant-700"
|
||||
iconStart="svg:SearchSvg"
|
||||
wrapperBorderClass="!border-dominant-50"
|
||||
customClass="placeholder:!text-dominant-300 !border-dominant-50 !font-normal !text-[11px] truncate"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 sm:gap-4 shrink-0 me-auto">
|
||||
<Link href="/dashboard/wallet" class="flex items-center gap-2.5 rounded-lg bg-dominant-light border border-dominant-50 ps-1.5 pe-3 py-1.5 transition-colors hover:border-dominant-100">
|
||||
<span class="flex items-center justify-center w-8 h-8 rounded-lg bg-white border border-dominant-50 text-dominant-400">
|
||||
<i class="fi fi-rr-wallet flex text-[15px]"></i>
|
||||
</span>
|
||||
<span class="flex flex-col max-sm:hidden">
|
||||
<span class="hidden md:flex flex-col">
|
||||
<span class="text-[10px] font-normal text-dominant-200">موجودی کیف پول</span>
|
||||
<span class="text-[12px] font-bold text-dominant-500">{{ walletBalance }} <span class="text-[10px] font-normal text-dominant-300">تومان</span></span>
|
||||
</span>
|
||||
</Link>
|
||||
<div class="flex items-center justify-center border-l-[1px] !border-dominant-50 pl-4">
|
||||
<div class="hidden sm:flex items-center justify-center border-l-[1px] !border-dominant-50 pl-4">
|
||||
<GlobalSvg />
|
||||
</div>
|
||||
<div ref="userMenuRef" class="relative">
|
||||
@@ -91,7 +85,7 @@ const menuItems = [
|
||||
<img v-if="globalStore.current_user.profile_url" :src="globalStore.current_user.profile_url" alt="تصویر پروفایل" class="w-full h-full object-cover" />
|
||||
<i v-else class="fi fi-rr-user flex text-sm text-dominant-300"></i>
|
||||
</span>
|
||||
<span class="text-dominant-300 text-[12px] font-normal max-sm:hidden">
|
||||
<span class="text-dominant-300 text-[12px] font-normal hidden md:inline">
|
||||
{{ globalStore.current_user.fullname }}
|
||||
</span>
|
||||
<i class="fi fi-rr-angle-small-down flex text-sm text-dominant-300 transition-transform duration-200" :class="{ 'rotate-180': userMenuOpen }"></i>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<script setup>
|
||||
import LandingSectionTitle from './LandingSectionTitle.vue'
|
||||
|
||||
const rows = [
|
||||
{ label: 'جابهجایی پت', before: 'سفر پراسترس تا کلینیک', after: 'پت در خانه میماند' },
|
||||
{ label: 'دسترسی به رادیولوژیست', before: 'وابسته به شهر و کلینیک', after: 'رادیولوژیست در شیفت، از هر جای ایران' },
|
||||
{ label: 'زمان دریافت گزارش', before: 'روزها و تماسهای پیگیری', after: '۲۴ ساعت عادی · ۳ ساعت اورژانسی' },
|
||||
{ label: 'خبردار شدن', before: 'باید خودتان زنگ بزنید', after: 'پیامک در هر مرحله' },
|
||||
{ label: 'نگهداری سوابق', before: 'کاغذ و CD گمشدنی', after: 'پروندهی دیجیتال دائمی' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="bg-light py-20 lg:py-28">
|
||||
<div class="container max-w-5xl px-4 sm:px-6">
|
||||
<LandingSectionTitle eyebrow="چرا رادیکال" title="همان گزارش تخصصی، بدون دردسرهایش" />
|
||||
|
||||
<div class="landing-reveal mt-14 overflow-hidden rounded-[28px] border-2 border-dominant-50 bg-white">
|
||||
<div class="grid grid-cols-[1.1fr_1fr_1fr] bg-dominant-50/40 text-xs sm:text-sm font-bold">
|
||||
<span class="px-4 sm:px-6 py-4 text-dark/50">مقایسه</span>
|
||||
<span class="px-4 sm:px-6 py-4 text-dark/50">مراجعهی حضوری</span>
|
||||
<span class="px-4 sm:px-6 py-4 bg-dominant-500 text-white flex items-center gap-2"><i class="fi fi-rr-paw leading-none text-[11px]"></i>رادیکال</span>
|
||||
</div>
|
||||
<dl>
|
||||
<div v-for="row in rows" :key="row.label" class="grid grid-cols-[1.1fr_1fr_1fr] border-t border-dominant-50 text-xs sm:text-sm">
|
||||
<dt class="px-4 sm:px-6 py-4 font-bold text-dark">{{ row.label }}</dt>
|
||||
<dd class="px-4 sm:px-6 py-4 text-dark/50 flex items-start gap-2"><i class="fi fi-rr-cross-small text-danger leading-none mt-1"></i>{{ row.before }}</dd>
|
||||
<dd class="px-4 sm:px-6 py-4 bg-dominant-50/50 font-semibold text-dark flex items-start gap-2"><i class="fi fi-rr-check text-success leading-none mt-1 text-[11px]"></i>{{ row.after }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,47 @@
|
||||
<script setup>
|
||||
import { Inertia } from '@inertiajs/inertia'
|
||||
import UiButton from '../ui/UiButton.vue'
|
||||
|
||||
defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="bg-white pb-20 lg:pb-28">
|
||||
<div class="container max-w-7xl px-4 sm:px-6">
|
||||
<div class="landing-reveal relative overflow-hidden rounded-[36px] bg-dark px-6 py-16 sm:px-12 lg:px-20 lg:py-20 grid lg:grid-cols-[1.3fr_1fr] gap-10 items-center">
|
||||
<svg class="absolute -bottom-16 -left-10 w-72 h-72 text-white/[0.04] pointer-events-none" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||
<path d="M8.35 3c1.18-.17 2.43 1.12 2.79 2.9.36 1.77-.29 3.35-1.47 3.53-1.17.18-2.43-1.11-2.8-2.89-.36-1.77.3-3.35 1.48-3.54zm7.3 0c1.18.19 1.84 1.77 1.48 3.54-.37 1.78-1.63 3.07-2.8 2.89-1.18-.18-1.83-1.76-1.47-3.53.36-1.78 1.61-3.07 2.79-2.9zM3 7.6c1.14-.49 2.72.38 3.53 1.95.81 1.56.55 3.22-.58 3.71-1.14.48-2.72-.39-3.53-1.95C1.61 9.75 1.87 8.09 3 7.6zm18 0c1.13.49 1.39 2.15.58 3.71-.81 1.56-2.39 2.43-3.53 1.95-1.13-.49-1.39-2.15-.58-3.71.81-1.57 2.39-2.44 3.53-1.95zM12 12c2.8 0 5.6 3.2 6.2 6.2.4 2-.8 3.8-3 3.8-1.2 0-2.2-.7-3.2-.7s-2 .7-3.2.7c-2.2 0-3.4-1.8-3-3.8C6.4 15.2 9.2 12 12 12z" />
|
||||
</svg>
|
||||
|
||||
<div class="relative">
|
||||
<h2 class="text-2xl sm:text-3xl lg:text-[2.6rem] font-black leading-[1.45] text-white">
|
||||
اولین پروندهی پتتان را
|
||||
<span class="text-dominant-300">همین امروز</span>
|
||||
باز کنید
|
||||
</h2>
|
||||
<p class="mt-5 max-w-lg text-base leading-8 text-white/60">
|
||||
ثبتنام فقط با شماره موبایل و در کمتر از یک دقیقه. تا وقتی درخواستی ثبت نکنید، هزینهای در کار نیست.
|
||||
</p>
|
||||
<div class="mt-8 flex flex-wrap items-center gap-4">
|
||||
<UiButton v-if="user" label="رفتن به پنل کاربری" severity="secondary" size="large" @click="Inertia.visit(route('dashboard.index'))" />
|
||||
<UiButton v-else label="ثبتنام بهعنوان سرپرست" severity="secondary" size="large" @click="Inertia.visit(route('register.chooseType'))" />
|
||||
<span class="text-xs text-white/40">بدون نیاز به کارت بانکی</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="relative space-y-3" aria-hidden="true">
|
||||
<li v-for="(item, i) in ['ساخت پروفایل پت', 'آپلود تصاویر', 'انتخاب رادیولوژیست', 'دریافت گزارش']" :key="item" class="flex items-center gap-3 rounded-2xl bg-white/5 border border-white/10 px-4 py-3 text-sm text-white/80">
|
||||
<span :class="i < 3 ? 'bg-success text-white' : 'bg-white/10 text-white/50'" class="w-6 h-6 rounded-full flex items-center justify-center text-[10px]"><i class="fi fi-rr-check leading-none"></i></span>
|
||||
{{ item }}
|
||||
<span v-if="i === 3" class="mr-auto text-[10px] text-dominant-300">پیامک ↓</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,54 @@
|
||||
<script setup>
|
||||
import LandingSectionTitle from './LandingSectionTitle.vue'
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
question: 'برای ثبتنام به چه چیزی نیاز دارم؟',
|
||||
answer: 'فقط شماره موبایل. با کد تأیید پیامکی وارد میشوید و بهعنوان «سرپرست» ثبتنام میکنید. نیازی به مدارک پزشکی یا پروانه نیست.'
|
||||
},
|
||||
{
|
||||
question: 'تصاویر را با چه فرمتی میتوانم بفرستم؟',
|
||||
answer: 'تصاویر و فایلهایی که مرکز تصویربرداری به شما داده (عکس، PDF یا فایل فشرده) را میتوانید مستقیم در فرم درخواست بارگذاری کنید. سوابق قبلی پت را هم میتوانید جداگانه ضمیمه کنید.'
|
||||
},
|
||||
{
|
||||
question: 'گزارش چقدر طول میکشد؟',
|
||||
answer: 'با اولویت عادی، مهلت بررسی پرونده ۲۴ ساعت پس از پرداخت است و با اولویت اورژانسی ۳ ساعت. اولویت را هنگام ثبت درخواست انتخاب میکنید.'
|
||||
},
|
||||
{
|
||||
question: 'گزارش را چطور دریافت میکنم؟',
|
||||
answer: 'بهمحض آماده شدن گزارش، پیامک دریافت میکنید و گزارش کامل همراه با پیوستهای پزشک در بخش «پروندهها»ی پنل شما قابل مشاهده و دانلود است. برای حفظ حریم خصوصی، متن گزارش هرگز در پیامک ارسال نمیشود.'
|
||||
},
|
||||
{
|
||||
question: 'اگر پزشک پرونده را رد کند چه میشود؟',
|
||||
answer: 'اگر تصاویر قابل گزارشدهی نباشند، پزشک با ذکر دلیل پرونده را رد میکند و مبلغ فاکتور بهصورت کامل به کیف پول شما بازگردانده میشود.'
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section id="faq" class="bg-white py-20 lg:py-28 scroll-mt-20">
|
||||
<div class="container max-w-7xl px-4 sm:px-6 grid lg:grid-cols-[1fr_1.6fr] gap-12 lg:gap-20 items-start">
|
||||
<div class="lg:sticky lg:top-28">
|
||||
<LandingSectionTitle class="!text-right !mx-0" eyebrow="سوالات متداول" title="چیزهایی که سرپرستان قبل از اولین درخواست میپرسند" />
|
||||
<p class="landing-reveal landing-reveal--2 mt-6 text-sm leading-7 text-dark/55">جوابتان را پیدا نکردید؟ بعد از ورود، از داخل پنل با ما در تماس باشید.</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3">
|
||||
<details
|
||||
v-for="(faq, index) in faqs"
|
||||
:key="faq.question"
|
||||
:class="`landing-reveal--${Math.min(index + 1, 5)}`"
|
||||
class="landing-faq landing-reveal group rounded-2xl bg-light border-2 border-transparent open:border-dominant-100 open:bg-white transition-colors duration-300"
|
||||
>
|
||||
<summary class="flex items-center justify-between gap-4 cursor-pointer list-none px-6 py-5 text-sm sm:text-base font-bold text-dark">
|
||||
{{ faq.question }}
|
||||
<span class="landing-faq-icon shrink-0 w-8 h-8 rounded-full bg-white border border-dominant-50 flex items-center justify-center text-dominant-500 transition-transform duration-300">
|
||||
<i class="fi fi-rr-plus text-xs leading-none"></i>
|
||||
</span>
|
||||
</summary>
|
||||
<p class="px-6 pb-6 text-sm leading-7 text-dark/60">{{ faq.answer }}</p>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,72 @@
|
||||
<script setup>
|
||||
import LandingSectionTitle from './LandingSectionTitle.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section id="features" class="bg-light py-20 lg:py-28 scroll-mt-20">
|
||||
<div class="container max-w-7xl px-4 sm:px-6">
|
||||
<LandingSectionTitle
|
||||
eyebrow="امکانات"
|
||||
title="ساختهشده برای کسی که نگران پتش است، نه برای کلینیک"
|
||||
description="بدون اصطلاحات تخصصی، بدون فرمهای طولانی. فقط چیزهایی که یک سرپرست واقعاً لازم دارد."
|
||||
/>
|
||||
|
||||
<div class="mt-14 grid gap-5 md:grid-cols-2 lg:grid-cols-4 lg:grid-rows-2">
|
||||
<article class="landing-reveal lg:col-span-2 lg:row-span-2 relative overflow-hidden rounded-[28px] bg-dark p-7 sm:p-9 text-white">
|
||||
<div class="landing-blob absolute -bottom-24 -left-24 w-72 h-72 bg-dominant-500/40 pointer-events-none" aria-hidden="true"></div>
|
||||
<div class="relative">
|
||||
<span class="inline-flex w-12 h-12 items-center justify-center rounded-2xl bg-white/10 text-xl"><i class="fi fi-rr-comment-alt-dots leading-none"></i></span>
|
||||
<h3 class="mt-6 text-2xl font-extrabold">در هر مرحله پیامک میگیرید</h3>
|
||||
<p class="mt-3 max-w-md text-sm leading-7 text-white/65">ثبت درخواست، پرداخت موفق و آماده شدن گزارش؛ سه پیامک، صفر پیگیری. متن گزارش هیچوقت در پیامک نیست — فقط خبرش.</p>
|
||||
</div>
|
||||
<div class="relative mt-8 mr-auto w-full max-w-[260px] rounded-[26px] bg-white/10 p-3" aria-hidden="true">
|
||||
<div class="rounded-[20px] bg-white p-3 space-y-2.5">
|
||||
<div class="landing-bubble rounded-xl rounded-tr-sm bg-light px-3 py-2 text-[11px] leading-5 text-dark">درخواست شما ثبت شد. شماره پرونده: ۲۶۴۹۵۸</div>
|
||||
<div class="landing-bubble rounded-xl rounded-tr-sm bg-light px-3 py-2 text-[11px] leading-5 text-dark">پرداخت فاکتور ۰۰۰۶۹ به مبلغ ۱٬۲۰۰٬۰۰۰ تومان انجام شد.</div>
|
||||
<div class="landing-bubble rounded-xl rounded-tr-sm bg-dominant-500 px-3 py-2 text-[11px] leading-5 text-white">گزارش پرونده ۲۶۴۹۵۸ آماده شد.</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="landing-reveal landing-reveal--1 lg:col-span-2 rounded-[28px] bg-white border-2 border-dominant-50 p-7 flex flex-col sm:flex-row sm:items-center gap-6">
|
||||
<div class="flex-1">
|
||||
<span class="inline-flex w-12 h-12 items-center justify-center rounded-2xl bg-dominant-50 text-dominant-500 text-xl"><i class="fi fi-rr-time-fast leading-none"></i></span>
|
||||
<h3 class="mt-5 text-lg font-extrabold text-dark">عادی یا اورژانسی؟ شما تعیین میکنید</h3>
|
||||
<p class="mt-2 text-sm leading-7 text-dark/60">مهلت بررسی با اولویت عادی ۲۴ ساعت است؛ با اورژانسی، ۳ ساعت.</p>
|
||||
</div>
|
||||
<div class="relative w-full sm:w-[200px] shrink-0 rounded-full bg-light p-1.5 grid grid-cols-2 text-center text-xs font-bold" aria-hidden="true">
|
||||
<span class="landing-toggle-thumb absolute top-1.5 bottom-1.5 right-1.5 w-[calc(50%-6px)] rounded-full bg-dominant-500"></span>
|
||||
<span class="relative z-10 py-2.5 text-white mix-blend-difference">عادی · ۲۴h</span>
|
||||
<span class="relative z-10 py-2.5 text-white mix-blend-difference">اورژانسی · ۳h</span>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="landing-reveal landing-reveal--2 rounded-[28px] bg-white border-2 border-dominant-50 p-7">
|
||||
<span class="inline-flex w-12 h-12 items-center justify-center rounded-2xl bg-dominant-50 text-dominant-500 text-xl"><i class="fi fi-rr-wallet leading-none"></i></span>
|
||||
<h3 class="mt-5 text-lg font-extrabold text-dark">پرداخت شفاف، برگشت کامل</h3>
|
||||
<p class="mt-2 text-sm leading-7 text-dark/60">قیمت هر خدمت قبل از پرداخت مشخص است. اگر پزشک پرونده را رد کند، کل مبلغ به کیف پول برمیگردد.</p>
|
||||
</article>
|
||||
|
||||
<article class="landing-reveal landing-reveal--3 rounded-[28px] bg-dominant-500 p-7 text-white">
|
||||
<span class="inline-flex w-12 h-12 items-center justify-center rounded-2xl bg-white/15 text-xl"><i class="fi fi-rr-lock-alt leading-none"></i></span>
|
||||
<h3 class="mt-5 text-lg font-extrabold">گزارش فقط برای شما</h3>
|
||||
<p class="mt-2 text-sm leading-7 text-white/70">گزارش و تصاویر فقط با ورود به حساب شما و توسط پزشک پرونده قابل مشاهدهاند؛ هیچ لینک عمومی وجود ندارد.</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<ul class="mt-5 grid gap-5 md:grid-cols-3">
|
||||
<li v-for="item in [
|
||||
{ icon: 'fi fi-rr-document', title: 'آرشیو دائمی پرونده', text: 'همهی تصاویر و گزارشهای هر پت، مرتب و قابل دانلود.' },
|
||||
{ icon: 'fi fi-rr-stethoscope', title: 'انتخاب پزشک یا شیفت خودکار', text: 'رادیولوژیست دلخواه، یا اختصاص فوری به پزشکِ در شیفت.' },
|
||||
{ icon: 'fi fi-rr-badge-check', title: 'رد پرونده با دلیل', text: 'اگر تصویر قابل گزارش نباشد، دلیلش را میبینید و هزینه برمیگردد.' },
|
||||
]" :key="item.title" class="landing-reveal flex items-start gap-4 rounded-2xl bg-white/60 border border-dominant-50 px-5 py-4">
|
||||
<i :class="item.icon" class="mt-1 text-dominant-500 leading-none"></i>
|
||||
<div>
|
||||
<h3 class="text-sm font-bold text-dark">{{ item.title }}</h3>
|
||||
<p class="mt-1 text-xs leading-6 text-dark/55">{{ item.text }}</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,48 @@
|
||||
<script setup>
|
||||
import { Link } from '@inertiajs/inertia-vue3'
|
||||
|
||||
const links = [
|
||||
{ label: 'چطور کار میکند', href: '#how-it-works' },
|
||||
{ label: 'امکانات', href: '#features' },
|
||||
{ label: 'خدمات تصویربرداری', href: '#modalities' },
|
||||
{ label: 'سوالات متداول', href: '#faq' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="bg-dominant-50 border-t border-dominant-100/60">
|
||||
<div class="container max-w-7xl px-4 sm:px-6 py-12 grid gap-10 md:grid-cols-[1.5fr_1fr_1fr]">
|
||||
<div>
|
||||
<Link href="/">
|
||||
<img src="@/images/radical_logo.png" alt="تلهرادیولوژی رادیکال" class="h-10 w-auto object-contain">
|
||||
</Link>
|
||||
<p class="mt-4 max-w-sm text-sm leading-7 text-dark/60">
|
||||
پلتفرم تلهرادیولوژی دامپزشکی رادیکال؛ پل ارتباطی سرپرستان حیوانات خانگی و رادیولوژیستهای دامپزشکی برای گزارشدهی تخصصی تصاویر پزشکی.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<nav aria-label="دسترسی سریع">
|
||||
<h3 class="text-sm font-bold text-dominant-700">دسترسی سریع</h3>
|
||||
<ul class="mt-4 space-y-2">
|
||||
<li v-for="link in links" :key="link.href">
|
||||
<a :href="link.href" class="text-sm text-dark/60 hover:text-dominant-500 transition-colors duration-200">{{ link.label }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<nav aria-label="حساب کاربری">
|
||||
<h3 class="text-sm font-bold text-dominant-700">حساب کاربری</h3>
|
||||
<ul class="mt-4 space-y-2">
|
||||
<li><Link :href="route('login')" class="text-sm text-dark/60 hover:text-dominant-500 transition-colors duration-200">ورود</Link></li>
|
||||
<li><Link :href="route('register.chooseType')" class="text-sm text-dark/60 hover:text-dominant-500 transition-colors duration-200">ثبتنام سرپرست</Link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-dominant-100/60">
|
||||
<p class="container max-w-7xl px-4 sm:px-6 py-5 text-center text-[13px] text-dominant-700">
|
||||
تمامی حقوق این وبسایت برای مجموعه <span class="font-semibold">تلهرادیولوژی رادیکال</span> محفوظ میباشد.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
@@ -0,0 +1,73 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Link } from '@inertiajs/inertia-vue3'
|
||||
import { Inertia } from '@inertiajs/inertia'
|
||||
import UiButton from '../ui/UiButton.vue'
|
||||
|
||||
defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
const isMenuOpen = ref(false)
|
||||
|
||||
const links = [
|
||||
{ label: 'چطور کار میکند', href: '#how-it-works' },
|
||||
{ label: 'امکانات', href: '#features' },
|
||||
{ label: 'خدمات تصویربرداری', href: '#modalities' },
|
||||
{ label: 'سوالات متداول', href: '#faq' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header class="sticky top-0 z-40 bg-white/90 backdrop-blur border-b border-dominant-50">
|
||||
<div class="container max-w-7xl px-4 sm:px-6 h-[72px] flex items-center justify-between gap-6">
|
||||
<Link href="/" class="shrink-0">
|
||||
<img src="@/images/radical_logo.png" alt="تلهرادیولوژی رادیکال" class="h-10 w-auto object-contain">
|
||||
</Link>
|
||||
|
||||
<nav class="hidden lg:block">
|
||||
<ul class="flex items-center gap-8">
|
||||
<li v-for="link in links" :key="link.href">
|
||||
<a :href="link.href" class="text-sm font-medium text-dark hover:text-dominant-500 transition-colors duration-200">
|
||||
{{ link.label }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="hidden lg:flex items-center gap-3">
|
||||
<template v-if="user">
|
||||
<UiButton label="ورود به پنل" severity="dominant" icon="fi fi-rr-user" @click="Inertia.visit(route('dashboard.index'))" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<UiButton label="ورود" severity="dominant" variant="text" text @click="Inertia.visit(route('login'))" />
|
||||
<UiButton label="ثبتنام رایگان" severity="dominant" @click="Inertia.visit(route('register.chooseType'))" />
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<button type="button" class="lg:hidden w-10 h-10 flex items-center justify-center rounded-lg text-dominant-700 hover:bg-dominant-50" :aria-expanded="isMenuOpen" aria-controls="landing-mobile-menu" aria-label="منو" @click="isMenuOpen = !isMenuOpen">
|
||||
<i :class="isMenuOpen ? 'fi fi-rr-cross' : 'fi fi-rr-menu-burger'" class="text-lg leading-none"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nav v-show="isMenuOpen" id="landing-mobile-menu" class="lg:hidden border-t border-dominant-50 bg-white">
|
||||
<ul class="container max-w-7xl px-4 py-4 flex flex-col gap-1">
|
||||
<li v-for="link in links" :key="link.href">
|
||||
<a :href="link.href" class="block px-3 py-2 rounded-lg text-sm font-medium text-dark hover:bg-dominant-50" @click="isMenuOpen = false">
|
||||
{{ link.label }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="pt-3 flex flex-col gap-2">
|
||||
<UiButton v-if="user" label="ورود به پنل" severity="dominant" full-width @click="Inertia.visit(route('dashboard.index'))" />
|
||||
<template v-else>
|
||||
<UiButton label="ثبتنام رایگان" severity="dominant" full-width @click="Inertia.visit(route('register.chooseType'))" />
|
||||
<UiButton label="ورود" severity="dominant" outlined full-width @click="Inertia.visit(route('login'))" />
|
||||
</template>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
</template>
|
||||
@@ -0,0 +1,75 @@
|
||||
<script setup>
|
||||
import { Link } from '@inertiajs/inertia-vue3'
|
||||
import { Inertia } from '@inertiajs/inertia'
|
||||
import UiButton from '../ui/UiButton.vue'
|
||||
|
||||
defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
const facts = [
|
||||
{ value: '۵', label: 'نوع تصویربرداری، از MRI تا رادیولوژی' },
|
||||
{ value: '۳ ساعت', label: 'مهلت گزارش برای پروندههای اورژانسی' },
|
||||
{ value: '۳ پیامک', label: 'ثبت، پرداخت، آماده شدن گزارش' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="relative min-h-[92svh] flex flex-col overflow-hidden bg-dark text-white">
|
||||
<img
|
||||
src="@/images/landing-hero.jpg"
|
||||
alt="یک گربه و یک سگ کنار هم روی چمن"
|
||||
class="landing-kenburns absolute inset-0 w-full h-full object-cover object-[30%_center] lg:object-[15%_center]"
|
||||
>
|
||||
<div class="absolute inset-0 bg-gradient-to-l from-dark via-dark/85 via-45% to-dark/25" aria-hidden="true"></div>
|
||||
<div class="absolute inset-x-0 bottom-0 h-2/3 bg-gradient-to-t from-dark via-dark/70 to-transparent" aria-hidden="true"></div>
|
||||
|
||||
<div class="container max-w-7xl px-4 sm:px-6 relative flex-1 flex flex-col justify-end pt-16 pb-10 lg:pb-14">
|
||||
<div class="max-w-3xl">
|
||||
<p class="landing-reveal text-xs sm:text-sm font-semibold tracking-wide text-dominant-300">
|
||||
تلهرادیولوژی دامپزشکی رادیکال
|
||||
</p>
|
||||
|
||||
<h1 class="mt-5 text-[2.6rem] leading-[1.25] sm:text-6xl lg:text-[5.2rem] lg:leading-[1.2] font-black">
|
||||
<span class="landing-reveal landing-reveal--1 block">اون که نگرانشی،</span>
|
||||
<span class="landing-reveal landing-reveal--2 block">لازم نیست از خونه</span>
|
||||
<span class="landing-reveal landing-reveal--3 block">بیرون بره<span class="text-dominant-300">.</span></span>
|
||||
</h1>
|
||||
|
||||
<p class="landing-reveal landing-reveal--4 mt-7 max-w-xl text-base sm:text-lg leading-8 text-white/70">
|
||||
تصاویر MRI، سیتیاسکن یا سونوگرافی پتتان را همینجا آپلود کنید؛ رادیولوژیست دامپزشکی گزارش مینویسد و شما با پیامک خبردار میشوید.
|
||||
</p>
|
||||
|
||||
<div class="landing-reveal landing-reveal--5 mt-9 flex flex-wrap items-center gap-6">
|
||||
<UiButton v-if="user" label="رفتن به پنل کاربری" severity="dominant" size="large" icon="fi fi-rr-arrow-small-left" icon-position="end" @click="Inertia.visit(route('dashboard.index'))" />
|
||||
<UiButton v-else label="ثبت اولین درخواست" severity="dominant" size="large" icon="fi fi-rr-arrow-small-left" icon-position="end" @click="Inertia.visit(route('register.chooseType'))" />
|
||||
<Link v-if="!user" :href="route('login')" class="text-sm font-semibold text-white/80 underline underline-offset-8 decoration-white/30 hover:text-white hover:decoration-dominant-300 transition-colors duration-200">
|
||||
قبلاً حساب دارم
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<dl class="landing-reveal landing-reveal--5 mt-14 lg:mt-20 grid sm:grid-cols-3 border-t border-white/15 pt-6 gap-6 sm:gap-0 sm:divide-x sm:divide-x-reverse sm:divide-white/15">
|
||||
<div v-for="fact in facts" :key="fact.label" class="sm:px-6 first:pr-0 last:pl-0">
|
||||
<dt class="text-2xl sm:text-3xl font-black text-white">{{ fact.value }}</dt>
|
||||
<dd class="mt-1 text-xs sm:text-sm leading-6 text-white/55">{{ fact.label }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<a href="#how-it-works" class="landing-spin absolute top-28 left-6 sm:left-10 hidden md:flex w-28 h-28 items-center justify-center rounded-full bg-dark/50 backdrop-blur-sm border border-white/15 text-white/85 hover:text-white hover:border-white/40 transition-colors duration-300" aria-label="ببینید چطور کار میکند">
|
||||
<svg viewBox="0 0 100 100" class="absolute inset-0 w-full h-full" aria-hidden="true">
|
||||
<defs>
|
||||
<path id="landing-hero-circle" d="M50,50 m-38,0 a38,38 0 1,1 76,0 a38,38 0 1,1 -76,0" />
|
||||
</defs>
|
||||
<text class="fill-current text-[9px] font-semibold tracking-[0.25em]">
|
||||
<textPath href="#landing-hero-circle">گزارش تخصصی · پیامک · بدون مراجعه ·</textPath>
|
||||
</text>
|
||||
</svg>
|
||||
<i class="fi fi-rr-arrow-small-down text-lg leading-none"></i>
|
||||
</a>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,16 @@
|
||||
<script setup>
|
||||
const items = ['MRI', 'سیتیاسکن', 'سونوگرافی', 'اکوکاردیوگرافی', 'رادیولوژی', 'سگ', 'گربه', 'خرگوش', 'پرنده', 'همستر', 'لاکپشت']
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="overflow-hidden border-y border-dominant-100/60 bg-dominant-500 py-4" aria-hidden="true">
|
||||
<div class="landing-marquee flex w-max">
|
||||
<ul v-for="copy in 2" :key="copy" class="flex shrink-0 items-center">
|
||||
<li v-for="item in items" :key="item" class="flex items-center gap-6 px-6 text-sm font-semibold text-white/90 whitespace-nowrap">
|
||||
{{ item }}
|
||||
<i class="fi fi-rr-paw text-[10px] text-white/40 leading-none"></i>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,55 @@
|
||||
<script setup>
|
||||
import LandingSectionTitle from './LandingSectionTitle.vue'
|
||||
|
||||
const modalities = [
|
||||
{ index: '۰۱', title: 'MRI', description: 'مغز، نخاع و بافتهای نرم؛ برای تشنج، لنگش عصبی و تودهها' },
|
||||
{ index: '۰۲', title: 'سیتیاسکن', description: 'استخوان، جمجمه، قفسهی سینه و شکم با جزئیات مقطعی' },
|
||||
{ index: '۰۳', title: 'سونوگرافی', description: 'اندامهای شکمی، بارداری، کلیه و کبد' },
|
||||
{ index: '۰۴', title: 'اکوکاردیوگرافی', description: 'ساختار و عملکرد قلب، دریچهها و جریان خون' },
|
||||
{ index: '۰۵', title: 'رادیولوژی', description: 'شکستگی، مفاصل، قفسهی سینه و اجسام خارجی' },
|
||||
]
|
||||
|
||||
const species = [
|
||||
{ icon: 'fi fi-rr-dog', label: 'سگ' },
|
||||
{ icon: 'fi fi-rr-cat', label: 'گربه' },
|
||||
{ icon: 'fi fi-rr-rabbit', label: 'خرگوش' },
|
||||
{ icon: 'fi fi-rr-bird', label: 'پرنده' },
|
||||
{ icon: 'fi fi-rr-turtle', label: 'لاکپشت' },
|
||||
{ icon: 'fi fi-rr-fish', label: 'ماهی' },
|
||||
{ icon: 'fi fi-rr-paw', label: 'همستر و خوکچه' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section id="modalities" class="bg-white py-20 lg:py-28 scroll-mt-20">
|
||||
<div class="container max-w-7xl px-4 sm:px-6 grid lg:grid-cols-[1fr_1.4fr] gap-12 lg:gap-20 items-start">
|
||||
<div class="lg:sticky lg:top-28">
|
||||
<LandingSectionTitle
|
||||
class="!text-right !mx-0"
|
||||
eyebrow="خدمات تصویربرداری"
|
||||
title="هر تصویری که دارید، جای خودش را دارد"
|
||||
description="تصویر را از هر مرکز تصویربرداری گرفته باشید فرقی نمیکند؛ فقط نوعش را انتخاب کنید."
|
||||
/>
|
||||
<ul class="landing-reveal landing-reveal--2 mt-8 flex flex-wrap gap-2">
|
||||
<li v-for="item in species" :key="item.label" class="flex items-center gap-2 rounded-full bg-light border border-dominant-50 px-3.5 py-2 text-xs font-semibold text-dark/70">
|
||||
<i :class="item.icon" class="text-dominant-500 leading-none"></i>
|
||||
{{ item.label }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ol class="divide-y-2 divide-dominant-50 border-y-2 border-dominant-50">
|
||||
<li
|
||||
v-for="(modality, index) in modalities"
|
||||
:key="modality.title"
|
||||
:class="`landing-reveal--${index + 1}`"
|
||||
class="landing-reveal group grid grid-cols-[3.5rem_1fr] sm:grid-cols-[5rem_11rem_1fr] items-center gap-4 py-6 transition-colors duration-300 hover:bg-white"
|
||||
>
|
||||
<span class="text-3xl sm:text-4xl font-black text-dominant-100 transition-colors duration-300 group-hover:text-dominant-500">{{ modality.index }}</span>
|
||||
<h3 class="text-xl sm:text-2xl font-extrabold text-dark">{{ modality.title }}</h3>
|
||||
<p class="col-span-2 sm:col-span-1 text-sm leading-7 text-dark/55 sm:pl-4">{{ modality.description }}</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,24 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
eyebrow: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="landing-reveal max-w-2xl mx-auto text-center">
|
||||
<span class="inline-block rounded-full bg-dominant-50 px-4 py-1.5 text-xs font-semibold text-dominant-500">{{ eyebrow }}</span>
|
||||
<h2 class="mt-4 text-2xl sm:text-3xl lg:text-4xl font-extrabold leading-[1.5] text-dark">{{ title }}</h2>
|
||||
<p v-if="description" class="mt-4 text-base leading-8 text-dark/60">{{ description }}</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,120 @@
|
||||
<script setup>
|
||||
import LandingSectionTitle from './LandingSectionTitle.vue'
|
||||
|
||||
const steps = [
|
||||
{
|
||||
number: '۰۱',
|
||||
title: 'پروفایل پت را بسازید',
|
||||
description: 'نام، گونه، نژاد، سن و وزن؛ یکبار ثبت میکنید و برای همهی درخواستهای بعدی آماده است. هر پت پروندهی مستقل خودش را دارد.',
|
||||
mock: 'pet'
|
||||
},
|
||||
{
|
||||
number: '۰۲',
|
||||
title: 'تصاویر را آپلود کنید',
|
||||
description: 'نوع تصویربرداری را انتخاب کنید، فایل اسکن و سوابق قبلی را بکشید و رها کنید. اگر عجله دارید، اولویت اورژانسی بگذارید.',
|
||||
mock: 'upload'
|
||||
},
|
||||
{
|
||||
number: '۰۳',
|
||||
title: 'رادیولوژیست را انتخاب کنید',
|
||||
description: 'پزشک مورد اعتمادتان را از لیست انتخاب کنید، یا بگذارید سیستم رادیولوژیستِ در شیفت را همان لحظه به پرونده اختصاص دهد.',
|
||||
mock: 'doctor'
|
||||
},
|
||||
{
|
||||
number: '۰۴',
|
||||
title: 'پیامک بگیرید، گزارش را بخوانید',
|
||||
description: 'بهمحض ثبت گزارش، پیامک میگیرید. گزارش کامل با تصاویر پیوست در پنل شماست؛ بدون تماس، بدون پیگیری.',
|
||||
mock: 'sms'
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section id="how-it-works" class="bg-white py-20 lg:py-28 scroll-mt-20">
|
||||
<div class="container max-w-7xl px-4 sm:px-6">
|
||||
<LandingSectionTitle
|
||||
eyebrow="چطور کار میکند"
|
||||
title="از عکس تا گزارش، چهار قدم"
|
||||
description="همان مسیری که در پنل طی میکنید؛ نه بیشتر."
|
||||
/>
|
||||
|
||||
<ol class="landing-reveal relative mt-16 space-y-10 lg:space-y-0">
|
||||
<span class="landing-timeline-line hidden lg:block absolute right-1/2 translate-x-1/2 top-0 bottom-0 w-0.5 bg-dominant-100" aria-hidden="true"></span>
|
||||
|
||||
<li
|
||||
v-for="(step, index) in steps"
|
||||
:key="step.number"
|
||||
class="relative grid lg:grid-cols-2 gap-8 lg:gap-24 items-center lg:py-10"
|
||||
>
|
||||
<span class="hidden lg:flex absolute right-1/2 translate-x-1/2 w-12 h-12 items-center justify-center rounded-full bg-dominant-500 text-white text-sm font-bold ring-8 ring-white" aria-hidden="true">{{ step.number }}</span>
|
||||
|
||||
<div :class="index % 2 === 0 ? 'lg:order-1 lg:pl-6' : 'lg:order-2 lg:pr-6'">
|
||||
<span class="lg:hidden inline-flex w-10 h-10 items-center justify-center rounded-full bg-dominant-500 text-white text-xs font-bold">{{ step.number }}</span>
|
||||
<h3 class="mt-4 lg:mt-0 text-xl sm:text-2xl font-extrabold text-dark">{{ step.title }}</h3>
|
||||
<p class="mt-3 text-sm sm:text-base leading-8 text-dark/60">{{ step.description }}</p>
|
||||
</div>
|
||||
|
||||
<div :class="index % 2 === 0 ? 'lg:order-2' : 'lg:order-1'" class="rounded-[28px] bg-light border-2 border-dominant-50 p-5 sm:p-7" aria-hidden="true">
|
||||
<div v-if="step.mock === 'pet'" class="rounded-2xl bg-white p-5 space-y-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="w-12 h-12 rounded-2xl bg-dominant-50 text-dominant-500 flex items-center justify-center text-xl"><i class="fi fi-rr-cat leading-none"></i></span>
|
||||
<div class="flex-1 space-y-1.5">
|
||||
<span class="block h-2 w-1/3 rounded-full bg-dark/10"></span>
|
||||
<span class="block h-2 w-1/5 rounded-full bg-dark/5"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-3 pt-2">
|
||||
<div v-for="field in ['نام: پیشی', 'گونه: گربه', 'سن: ۳ سال', 'وزن: ۴.۲ کیلو']" :key="field" class="rounded-xl border border-dominant-50 px-3 py-2.5 text-xs text-dark/70">{{ field }}</div>
|
||||
</div>
|
||||
<div class="flex justify-end pt-1">
|
||||
<span class="rounded-lg bg-dominant-500 px-4 py-2 text-[11px] font-semibold text-white">ذخیرهی پروفایل</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="step.mock === 'upload'" class="rounded-2xl bg-white p-5 space-y-3">
|
||||
<div class="flex gap-2">
|
||||
<span v-for="(modality, i) in ['MRI', 'سیتی', 'سونو', 'اکو']" :key="modality" :class="i === 0 ? 'bg-dominant-500 text-white' : 'bg-dominant-50 text-dark/60'" class="rounded-full px-3 py-1 text-[11px] font-semibold">{{ modality }}</span>
|
||||
</div>
|
||||
<div class="rounded-2xl border-2 border-dashed border-dominant-200 bg-light/60 p-5 text-center">
|
||||
<i class="fi fi-rr-cloud-upload text-2xl text-dominant-500 leading-none"></i>
|
||||
<p class="mt-2 text-xs font-semibold text-dark">فایلها را اینجا رها کنید</p>
|
||||
</div>
|
||||
<ul class="space-y-2">
|
||||
<li v-for="file in ['Pishi_MRI_T2.zip · ۴۸ MB', 'سابقهی آزمایش خون.pdf']" :key="file" class="flex items-center justify-between rounded-xl bg-light px-3 py-2 text-[11px] text-dark/70">
|
||||
{{ file }}
|
||||
<i class="fi fi-rr-check-circle text-success leading-none"></i>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="flex items-center justify-between rounded-xl bg-dominant-50 px-3 py-2 text-[11px] font-semibold text-dominant-700">
|
||||
اولویت
|
||||
<span class="flex gap-1"><span class="rounded-md bg-white px-2 py-0.5">عادی</span><span class="rounded-md bg-dominant-500 px-2 py-0.5 text-white">اورژانسی</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="step.mock === 'doctor'" class="space-y-3">
|
||||
<div v-for="(doctor, i) in [{ name: 'دکتر آرمان صادقی', spec: 'رادیولوژیست · MRI و CT', shift: true }, { name: 'دکتر نگار کریمی', spec: 'رادیولوژیست · سونوگرافی', shift: false }]" :key="doctor.name" :class="i === 0 ? 'border-dominant-500' : 'border-transparent'" class="flex items-center gap-3 rounded-2xl bg-white border-2 p-4">
|
||||
<span class="w-11 h-11 rounded-full bg-dark text-white flex items-center justify-center"><i class="fi fi-rr-user-md leading-none"></i></span>
|
||||
<div class="flex-1">
|
||||
<p class="text-xs font-bold text-dark">{{ doctor.name }}</p>
|
||||
<p class="text-[10px] text-dark/50">{{ doctor.spec }}</p>
|
||||
</div>
|
||||
<span v-if="doctor.shift" class="flex items-center gap-1.5 rounded-full bg-complement-50 px-2.5 py-1 text-[10px] font-semibold text-complement-700"><span class="w-1.5 h-1.5 rounded-full bg-success"></span>در شیفت</span>
|
||||
<span v-else class="text-[10px] text-dark/40">شیفت بعدی: ۱۸:۰۰</span>
|
||||
</div>
|
||||
<p class="text-center text-[11px] text-dark/50">یا <span class="font-semibold text-dominant-500">انتخاب خودکار</span> پزشکِ در شیفت</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="mx-auto w-full max-w-[280px] rounded-[30px] bg-dark p-3">
|
||||
<div class="rounded-[22px] bg-white p-4 space-y-3 min-h-[230px]">
|
||||
<p class="text-center text-[10px] text-dark/40">رادیکال</p>
|
||||
<div class="landing-bubble rounded-2xl rounded-tr-md bg-light px-3 py-2.5 text-[11px] leading-5 text-dark">درخواست شما ثبت شد. شماره پرونده: ۲۶۴۹۵۸</div>
|
||||
<div class="landing-bubble rounded-2xl rounded-tr-md bg-light px-3 py-2.5 text-[11px] leading-5 text-dark">پرداخت فاکتور ۰۰۰۶۹ با موفقیت انجام شد. پرونده به پزشک ارجاع شد.</div>
|
||||
<div class="landing-bubble rounded-2xl rounded-tr-md bg-dominant-500 px-3 py-2.5 text-[11px] leading-5 text-white">گزارش پرونده ۲۶۴۹۵۸ آماده شد. برای مشاهده به پنل مراجعه کنید.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -176,12 +176,12 @@ const updateExpandedKeys = () => {
|
||||
|
||||
<template>
|
||||
<div v-if="globalStore.sidebarOpen"
|
||||
class="fixed inset-0 bg-black/10 backdrop-blur-sm bg-opacity-50 z-10 sm:hidden"
|
||||
class="fixed inset-0 bg-black/10 backdrop-blur-sm bg-opacity-50 z-10 lg:hidden"
|
||||
@click="globalStore.sidebarOpen = false">
|
||||
</div>
|
||||
<aside class="shadow-client-gray/5 w-[16rem] bg-white
|
||||
py-4 pt-0 pb-8 fixed h-full top-0 z-30 inset-y-0 right-0 sm:inset-auto transition-transform duration-300"
|
||||
:class="[globalStore.sidebarOpen ? 'translate-x-0' : 'translate-x-full sm:translate-x-0']">
|
||||
py-4 pt-0 pb-8 fixed h-full top-0 z-30 inset-y-0 right-0 lg:inset-auto transition-transform duration-300"
|
||||
:class="[globalStore.sidebarOpen ? 'translate-x-0' : 'translate-x-full lg:translate-x-0']">
|
||||
<figure class="w-[16rem] h-[5rem] flex justify-center">
|
||||
<img class="!w-full h-full object-contain" src="@/images/SidebarPanelLogo.png" alt="">
|
||||
</figure>
|
||||
|
||||
@@ -123,6 +123,7 @@ const getColumnStyle = (column) => {
|
||||
</template>
|
||||
</Toolbar>
|
||||
</div>
|
||||
<div class="table-generic-scroll">
|
||||
<DataTable
|
||||
:value="data"
|
||||
dataKey="id"
|
||||
@@ -159,6 +160,7 @@ const getColumnStyle = (column) => {
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
<Pagination
|
||||
v-if="pagination && pagination.total"
|
||||
@@ -172,8 +174,3 @@ const getColumnStyle = (column) => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.table-generic {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { onBeforeUnmount, onMounted } from 'vue'
|
||||
|
||||
export function useScrollReveal(rootRef, selector = '.landing-reveal') {
|
||||
let observer = null
|
||||
|
||||
onMounted(() => {
|
||||
const elements = rootRef.value?.querySelectorAll(selector) ?? []
|
||||
|
||||
if (!('IntersectionObserver' in window)) {
|
||||
elements.forEach((element) => element.classList.add('is-visible'))
|
||||
return
|
||||
}
|
||||
|
||||
observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('is-visible')
|
||||
observer.unobserve(entry.target)
|
||||
}
|
||||
})
|
||||
}, { threshold: 0.05 })
|
||||
|
||||
elements.forEach((element) => observer.observe(element))
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => observer?.disconnect())
|
||||
}
|
||||
@@ -19,8 +19,8 @@ onMounted(() => {
|
||||
<header-component />
|
||||
<div class="!bg-white">
|
||||
<section class="">
|
||||
<main class="overflow-hidden !ps-[16rem] max-sm:!ps-4 pt-20 min-h-[calc(100svh)] p-4 grid grid-cols-1">
|
||||
<section class="!rounded-2xl border-[1px] border-dominant-50 !bg-dominant-50/50 content-start p-4 grid grid-cols-1">
|
||||
<main class="overflow-hidden lg:!ps-[16rem] pt-20 min-h-[calc(100svh)] p-4 grid grid-cols-1">
|
||||
<section class="!rounded-2xl border-[1px] border-dominant-50 !bg-dominant-50/50 content-start p-3 sm:p-4 grid grid-cols-1 min-w-0">
|
||||
<div v-if="$page.props.flash.success" class="w-full mb-4">
|
||||
<Message size="small" closable class="!text-xs py-1.5" severity="success">{{$page.props.flash.success}}</Message>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user