Compare commits
3 Commits
a0190bc7ad
...
e4ab9d2a12
| Author | SHA1 | Date | |
|---|---|---|---|
| e4ab9d2a12 | |||
| b4e06b641d | |||
| e8eff6c2cb |
BIN
public/qlockify-profile-dark.png
Normal file
BIN
public/qlockify-profile-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
public/qlockify-profile-light.png
Normal file
BIN
public/qlockify-profile-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -64,6 +64,49 @@
|
|||||||
"Project access and user roles help limit what each person can see or use.",
|
"Project access and user roles help limit what each person can see or use.",
|
||||||
"Exports and logs are designed to make review easier, not to hide important details."
|
"Exports and logs are designed to make review easier, not to hide important details."
|
||||||
],
|
],
|
||||||
|
"contact": {
|
||||||
|
"eyebrow": "Contact",
|
||||||
|
"title": "Need help or want to talk about Qlockify?",
|
||||||
|
"description": "Send a note or reach out through the support channels below. The form opens an email draft with your message so you can review it before sending.",
|
||||||
|
"formTitle": "Send a note",
|
||||||
|
"fields": {
|
||||||
|
"firstName": "First name",
|
||||||
|
"lastName": "Last name",
|
||||||
|
"email": "Email",
|
||||||
|
"mobile": "Mobile",
|
||||||
|
"message": "Message"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"firstName": "Your first name",
|
||||||
|
"lastName": "Your last name",
|
||||||
|
"email": "you@example.com",
|
||||||
|
"mobile": "09...",
|
||||||
|
"message": "Tell us what you need help with..."
|
||||||
|
},
|
||||||
|
"submit": "Prepare email",
|
||||||
|
"channels": [
|
||||||
|
{
|
||||||
|
"label": "Telegram support",
|
||||||
|
"value": "qlockify_support",
|
||||||
|
"href": "https://t.me/qlockify_support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Telegram channel",
|
||||||
|
"value": "qlockify",
|
||||||
|
"href": "https://t.me/qlockify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Support email",
|
||||||
|
"value": "qlockify@gmail.com",
|
||||||
|
"href": "mailto:qlockify@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Mobile (message or call)",
|
||||||
|
"value": "09938228438",
|
||||||
|
"href": "tel:09938228438"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"cta": {
|
"cta": {
|
||||||
"title": "Start with one workspace and make time easier to explain.",
|
"title": "Start with one workspace and make time easier to explain.",
|
||||||
"description": "Open Qlockify, track a real workday, and compare the report with the way your team reviews work today.",
|
"description": "Open Qlockify, track a real workday, and compare the report with the way your team reviews work today.",
|
||||||
@@ -135,6 +178,49 @@
|
|||||||
"دسترسی پروژه و نقش کاربران کمک میکند هر فرد فقط چیزی را ببیند یا استفاده کند که باید.",
|
"دسترسی پروژه و نقش کاربران کمک میکند هر فرد فقط چیزی را ببیند یا استفاده کند که باید.",
|
||||||
"خروجیها و لاگها برای سادهتر کردن بررسی طراحی شدهاند، نه برای پنهان کردن جزئیات مهم."
|
"خروجیها و لاگها برای سادهتر کردن بررسی طراحی شدهاند، نه برای پنهان کردن جزئیات مهم."
|
||||||
],
|
],
|
||||||
|
"contact": {
|
||||||
|
"eyebrow": "تماس",
|
||||||
|
"title": "کمک میخواهید یا میخواهید درباره Qlockify صحبت کنیم؟",
|
||||||
|
"description": "یک پیام بفرستید یا از مسیرهای پشتیبانی زیر با ما در ارتباط باشید. فرم یک پیشنویس ایمیل با پیام شما آماده میکند تا قبل از ارسال آن را بررسی کنید.",
|
||||||
|
"formTitle": "ارسال پیام",
|
||||||
|
"fields": {
|
||||||
|
"firstName": "نام",
|
||||||
|
"lastName": "نام خانوادگی",
|
||||||
|
"email": "ایمیل",
|
||||||
|
"mobile": "موبایل",
|
||||||
|
"message": "پیام"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"firstName": "نام شما",
|
||||||
|
"lastName": "نام خانوادگی شما",
|
||||||
|
"email": "you@example.com",
|
||||||
|
"mobile": "09...",
|
||||||
|
"message": "بگویید برای چه چیزی به کمک نیاز دارید..."
|
||||||
|
},
|
||||||
|
"submit": "آمادهسازی ایمیل",
|
||||||
|
"channels": [
|
||||||
|
{
|
||||||
|
"label": "پشتیبانی تلگرام",
|
||||||
|
"value": "qlockify_support",
|
||||||
|
"href": "https://t.me/qlockify_support"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "کانال تلگرام",
|
||||||
|
"value": "qlockify",
|
||||||
|
"href": "https://t.me/qlockify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "ایمیل پشتیبانی",
|
||||||
|
"value": "qlockify@gmail.com",
|
||||||
|
"href": "mailto:qlockify@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "موبایل (پیام یا تماس)",
|
||||||
|
"value": "09938228438",
|
||||||
|
"href": "tel:09938228438"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"cta": {
|
"cta": {
|
||||||
"title": "با یک ورکاسپیس شروع کنید و توضیح زمان را سادهتر کنید.",
|
"title": "با یک ورکاسپیس شروع کنید و توضیح زمان را سادهتر کنید.",
|
||||||
"description": "Qlockify را باز کنید، یک روز کاری واقعی را ثبت کنید و گزارش آن را با روش فعلی مرور کار در تیم مقایسه کنید.",
|
"description": "Qlockify را باز کنید، یک روز کاری واقعی را ثبت کنید و گزارش آن را با روش فعلی مرور کار در تیم مقایسه کنید.",
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import { useState, type FormEvent } from "react"
|
||||||
import { Link, useNavigate } from "react-router-dom"
|
import { Link, useNavigate } from "react-router-dom"
|
||||||
import {
|
import {
|
||||||
ArrowLeft,
|
ArrowLeft,
|
||||||
ArrowRight,
|
ArrowRight,
|
||||||
|
AtSign,
|
||||||
BarChart3,
|
BarChart3,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
Command,
|
Command,
|
||||||
@@ -9,7 +11,11 @@ import {
|
|||||||
Globe2,
|
Globe2,
|
||||||
Layers3,
|
Layers3,
|
||||||
LockKeyhole,
|
LockKeyhole,
|
||||||
|
Mail,
|
||||||
|
MessageCircle,
|
||||||
Moon,
|
Moon,
|
||||||
|
Phone,
|
||||||
|
Send,
|
||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
Sparkles,
|
Sparkles,
|
||||||
Sun,
|
Sun,
|
||||||
@@ -19,6 +25,8 @@ import {
|
|||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
|
|
||||||
import { Button } from "../components/ui/button"
|
import { Button } from "../components/ui/button"
|
||||||
|
import { Input } from "../components/ui/input"
|
||||||
|
import { TextAreaInput } from "../components/ui/TextAreaInput"
|
||||||
import { useTheme } from "../components/ThemeProvider"
|
import { useTheme } from "../components/ThemeProvider"
|
||||||
import { useTranslation } from "../hooks/useTranslation"
|
import { useTranslation } from "../hooks/useTranslation"
|
||||||
import aboutContent from "../content/about.json"
|
import aboutContent from "../content/about.json"
|
||||||
@@ -29,11 +37,19 @@ type AboutContent = typeof aboutContent.en
|
|||||||
const sectionIcons = [Sparkles, ShieldCheck, Layers3]
|
const sectionIcons = [Sparkles, ShieldCheck, Layers3]
|
||||||
const principleIcons = [TimerReset, Waypoints, BarChart3]
|
const principleIcons = [TimerReset, Waypoints, BarChart3]
|
||||||
const capabilityIcons = [TimerReset, Users, FileText, LockKeyhole]
|
const capabilityIcons = [TimerReset, Users, FileText, LockKeyhole]
|
||||||
|
const contactIcons = [MessageCircle, MessageCircle, Mail, Phone]
|
||||||
|
|
||||||
export default function About() {
|
export default function About() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { t, lang, setLanguage } = useTranslation()
|
const { t, lang, setLanguage } = useTranslation()
|
||||||
const { theme, setTheme } = useTheme()
|
const { theme, setTheme } = useTheme()
|
||||||
|
const [contactForm, setContactForm] = useState({
|
||||||
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
|
email: "",
|
||||||
|
mobile: "",
|
||||||
|
message: "",
|
||||||
|
})
|
||||||
|
|
||||||
const content = aboutContent[lang] as AboutContent
|
const content = aboutContent[lang] as AboutContent
|
||||||
const isAuthenticated = typeof window !== "undefined" && !!localStorage.getItem("accessToken")
|
const isAuthenticated = typeof window !== "undefined" && !!localStorage.getItem("accessToken")
|
||||||
@@ -42,6 +58,27 @@ export default function About() {
|
|||||||
(theme === "system" && document.documentElement.classList.contains("dark"))
|
(theme === "system" && document.documentElement.classList.contains("dark"))
|
||||||
const ctaTarget = isAuthenticated ? "/timesheet" : "/auth"
|
const ctaTarget = isAuthenticated ? "/timesheet" : "/auth"
|
||||||
|
|
||||||
|
const updateContactField = (field: keyof typeof contactForm, value: string) => {
|
||||||
|
setContactForm((current) => ({ ...current, [field]: value }))
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitContactForm = (event: FormEvent<HTMLFormElement>) => {
|
||||||
|
event.preventDefault()
|
||||||
|
const subject = encodeURIComponent("Qlockify contact request")
|
||||||
|
const body = encodeURIComponent(
|
||||||
|
[
|
||||||
|
`First name: ${contactForm.firstName}`,
|
||||||
|
`Last name: ${contactForm.lastName}`,
|
||||||
|
`Email: ${contactForm.email}`,
|
||||||
|
`Mobile: ${contactForm.mobile}`,
|
||||||
|
"",
|
||||||
|
"Message:",
|
||||||
|
contactForm.message,
|
||||||
|
].join("\n"),
|
||||||
|
)
|
||||||
|
window.location.href = `mailto:qlockify@gmail.com?subject=${subject}&body=${body}`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="scroll-smooth min-h-screen overflow-x-hidden bg-[radial-gradient(circle_at_top,#e0f2fe_0%,#f8fafc_36%,#eef2ff_100%)] text-slate-950 dark:bg-[radial-gradient(circle_at_top,#082f49_0%,#020617_40%,#020617_100%)] dark:text-slate-50">
|
<div className="scroll-smooth min-h-screen overflow-x-hidden bg-[radial-gradient(circle_at_top,#e0f2fe_0%,#f8fafc_36%,#eef2ff_100%)] text-slate-950 dark:bg-[radial-gradient(circle_at_top,#082f49_0%,#020617_40%,#020617_100%)] dark:text-slate-50">
|
||||||
<div className="landing-aurora pointer-events-none fixed inset-0 opacity-80" />
|
<div className="landing-aurora pointer-events-none fixed inset-0 opacity-80" />
|
||||||
@@ -291,6 +328,132 @@ export default function About() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section className="grid gap-6 py-8 lg:grid-cols-[0.95fr_1.05fr]">
|
||||||
|
<div className="animate-landing-rise rounded-[2rem] border border-white/70 bg-white/80 p-7 shadow-[0_30px_80px_-50px_rgba(15,23,42,0.6)] backdrop-blur-xl dark:border-white/10 dark:bg-slate-950/65">
|
||||||
|
<div className="text-sm font-semibold uppercase tracking-[0.2em] text-cyan-700 dark:text-cyan-300">
|
||||||
|
{content.contact.eyebrow}
|
||||||
|
</div>
|
||||||
|
<h2 className="mt-4 text-4xl font-semibold tracking-[-0.05em] text-slate-950 dark:text-white">
|
||||||
|
{content.contact.title}
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 text-base leading-8 text-slate-600 dark:text-slate-300">
|
||||||
|
{content.contact.description}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mt-7 grid gap-3">
|
||||||
|
{content.contact.channels.map((channel, index) => {
|
||||||
|
const Icon = contactIcons[index] ?? AtSign
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={channel.label}
|
||||||
|
href={channel.href}
|
||||||
|
target={channel.href.startsWith("http") ? "_blank" : undefined}
|
||||||
|
rel={channel.href.startsWith("http") ? "noreferrer" : undefined}
|
||||||
|
className="group flex items-center justify-between gap-4 rounded-2xl border border-slate-200/80 bg-white/80 p-4 text-start shadow-sm transition hover:border-cyan-300 hover:bg-cyan-50/70 dark:border-slate-800 dark:bg-slate-900/75 dark:hover:border-cyan-500/40 dark:hover:bg-cyan-950/30"
|
||||||
|
>
|
||||||
|
<span className="flex min-w-0 items-center gap-3">
|
||||||
|
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-slate-950 text-white dark:bg-cyan-400 dark:text-slate-950">
|
||||||
|
<Icon className="h-5 w-5" />
|
||||||
|
</span>
|
||||||
|
<span className="min-w-0">
|
||||||
|
<span className="block text-sm font-semibold text-slate-950 dark:text-white">
|
||||||
|
{channel.label}
|
||||||
|
</span>
|
||||||
|
<span className="block truncate text-sm text-slate-600 dark:text-slate-300">
|
||||||
|
{channel.value}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
{lang === "fa" ? (
|
||||||
|
<ArrowLeft className="h-4 w-4 shrink-0 text-slate-400 transition group-hover:text-cyan-600 dark:group-hover:text-cyan-300" />
|
||||||
|
) : (
|
||||||
|
<ArrowRight className="h-4 w-4 shrink-0 text-slate-400 transition group-hover:text-cyan-600 dark:group-hover:text-cyan-300" />
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form
|
||||||
|
onSubmit={submitContactForm}
|
||||||
|
className="animate-landing-rise rounded-[2rem] border border-white/70 bg-white/85 p-7 shadow-[0_30px_80px_-50px_rgba(15,23,42,0.6)] backdrop-blur-xl dark:border-white/10 dark:bg-slate-950/70"
|
||||||
|
>
|
||||||
|
<div className="mb-6 flex items-center gap-3">
|
||||||
|
<span className="flex h-11 w-11 items-center justify-center rounded-2xl bg-slate-950 text-white dark:bg-cyan-400 dark:text-slate-950">
|
||||||
|
<Send className="h-5 w-5" />
|
||||||
|
</span>
|
||||||
|
<h2 className="text-2xl font-semibold tracking-[-0.04em] text-slate-950 dark:text-white">
|
||||||
|
{content.contact.formTitle}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-4 sm:grid-cols-2">
|
||||||
|
<label className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||||
|
{content.contact.fields.firstName}
|
||||||
|
<Input
|
||||||
|
value={contactForm.firstName}
|
||||||
|
onChange={(event) => updateContactField("firstName", event.target.value)}
|
||||||
|
placeholder={content.contact.placeholders.firstName}
|
||||||
|
className="mt-2 h-12 rounded-2xl"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||||
|
{content.contact.fields.lastName}
|
||||||
|
<Input
|
||||||
|
value={contactForm.lastName}
|
||||||
|
onChange={(event) => updateContactField("lastName", event.target.value)}
|
||||||
|
placeholder={content.contact.placeholders.lastName}
|
||||||
|
className="mt-2 h-12 rounded-2xl"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||||
|
{content.contact.fields.email}
|
||||||
|
<Input
|
||||||
|
type="email"
|
||||||
|
value={contactForm.email}
|
||||||
|
onChange={(event) => updateContactField("email", event.target.value)}
|
||||||
|
placeholder={content.contact.placeholders.email}
|
||||||
|
className="mt-2 h-12 rounded-2xl"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||||
|
{content.contact.fields.mobile}
|
||||||
|
<Input
|
||||||
|
value={contactForm.mobile}
|
||||||
|
onChange={(event) => updateContactField("mobile", event.target.value)}
|
||||||
|
placeholder={content.contact.placeholders.mobile}
|
||||||
|
className="mt-2 h-12 rounded-2xl"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label className="mt-4 block text-sm font-medium text-slate-700 dark:text-slate-300">
|
||||||
|
{content.contact.fields.message}
|
||||||
|
<TextAreaInput
|
||||||
|
value={contactForm.message}
|
||||||
|
onChange={(event) => updateContactField("message", event.target.value)}
|
||||||
|
placeholder={content.contact.placeholders.message}
|
||||||
|
className="mt-2 min-h-40 rounded-2xl"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className="mt-6 h-14 w-full rounded-full bg-slate-950 px-7 text-base text-white hover:bg-slate-800 dark:bg-cyan-400 dark:text-slate-950 dark:hover:bg-cyan-300"
|
||||||
|
>
|
||||||
|
<Send className="me-2 h-4 w-4" />
|
||||||
|
{content.contact.submit}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section className="py-8">
|
<section className="py-8">
|
||||||
<div className="relative overflow-hidden rounded-[2.5rem] border border-slate-950/5 bg-slate-950 px-6 py-10 text-white shadow-[0_40px_100px_-40px_rgba(15,23,42,0.8)] dark:border-white/10 sm:px-10">
|
<div className="relative overflow-hidden rounded-[2.5rem] border border-slate-950/5 bg-slate-950 px-6 py-10 text-white shadow-[0_40px_100px_-40px_rgba(15,23,42,0.8)] dark:border-white/10 sm:px-10">
|
||||||
<div className="pointer-events-none absolute inset-y-0 right-0 w-[45%] bg-[radial-gradient(circle_at_top_right,rgba(34,211,238,0.35),transparent_55%),radial-gradient(circle_at_bottom_right,rgba(16,185,129,0.24),transparent_45%)]" />
|
<div className="pointer-events-none absolute inset-y-0 right-0 w-[45%] bg-[radial-gradient(circle_at_top_right,rgba(34,211,238,0.35),transparent_55%),radial-gradient(circle_at_bottom_right,rgba(16,185,129,0.24),transparent_45%)]" />
|
||||||
|
|||||||
@@ -1,70 +1,48 @@
|
|||||||
import { Link, useLocation } from "react-router-dom"
|
import { useNavigate } from "react-router-dom"
|
||||||
import { ArrowLeft, ArrowRight, Command, Compass, Home } from "lucide-react"
|
import { ArrowLeft, ArrowRight, Home } from "lucide-react"
|
||||||
|
|
||||||
import { Button } from "../components/ui/button"
|
import { Button } from "../components/ui/button"
|
||||||
import { useTranslation } from "../hooks/useTranslation"
|
import { useTranslation } from "../hooks/useTranslation"
|
||||||
import { cn } from "../lib/utils"
|
|
||||||
|
|
||||||
export default function NotFound() {
|
export default function NotFound() {
|
||||||
const location = useLocation()
|
const navigate = useNavigate()
|
||||||
const { lang, t } = useTranslation()
|
const { lang } = useTranslation()
|
||||||
const isFa = lang === "fa"
|
const isFa = lang === "fa"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen overflow-hidden bg-[radial-gradient(circle_at_top,#e0f2fe_0%,#f8fafc_36%,#eef2ff_100%)] text-slate-950 dark:bg-[radial-gradient(circle_at_top,#082f49_0%,#020617_40%,#020617_100%)] dark:text-slate-50">
|
<main className="flex min-h-screen items-center justify-center bg-[radial-gradient(circle_at_top,#e0f2fe_0%,#f8fafc_42%,#eef2ff_100%)] px-4 text-center text-slate-950 dark:bg-[radial-gradient(circle_at_top,#082f49_0%,#020617_44%,#020617_100%)] dark:text-slate-50">
|
||||||
<div className="landing-aurora pointer-events-none fixed inset-0 opacity-80" />
|
<section className="mx-auto max-w-2xl">
|
||||||
<div className="landing-hero-grid pointer-events-none fixed inset-0 opacity-70 dark:opacity-40" />
|
<div className="text-[7rem] font-semibold leading-none tracking-[-0.08em] text-slate-950 sm:text-[10rem] dark:text-white">
|
||||||
|
404
|
||||||
<main className="relative mx-auto flex min-h-screen max-w-5xl items-center px-4 py-12 sm:px-6 lg:px-8">
|
|
||||||
<div className="animate-landing-rise w-full overflow-hidden rounded-[2.5rem] border border-white/70 bg-white/80 p-6 shadow-[0_45px_110px_-48px_rgba(15,23,42,0.6)] backdrop-blur-2xl dark:border-white/10 dark:bg-slate-950/70 sm:p-10">
|
|
||||||
<div className="flex flex-col gap-8 lg:flex-row lg:items-end lg:justify-between">
|
|
||||||
<div className="max-w-3xl">
|
|
||||||
<div className="mb-5 inline-flex items-center gap-2 rounded-full border border-cyan-200/70 bg-cyan-50/80 px-4 py-2 text-sm font-semibold text-cyan-900 dark:border-cyan-500/20 dark:bg-cyan-500/10 dark:text-cyan-100">
|
|
||||||
<Compass className="h-4 w-4" />
|
|
||||||
{isFa ? "مسیر پیدا نشد" : "Route not found"}
|
|
||||||
</div>
|
|
||||||
<h1 className="text-5xl font-semibold tracking-[-0.06em] text-slate-950 sm:text-7xl dark:text-white">
|
|
||||||
404
|
|
||||||
</h1>
|
|
||||||
<p className="mt-5 text-xl leading-9 text-slate-600 dark:text-slate-300">
|
|
||||||
{isFa
|
|
||||||
? "این آدرس در رابط کاربری Qlockify تعریف نشده است."
|
|
||||||
: "This endpoint is not defined in the Qlockify interface."}
|
|
||||||
</p>
|
|
||||||
<div className="mt-6 rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 font-mono text-sm text-slate-700 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-200">
|
|
||||||
{location.pathname}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-3 sm:flex-row lg:flex-col">
|
|
||||||
<Button
|
|
||||||
asChild
|
|
||||||
className="h-14 rounded-full bg-slate-950 px-7 text-base text-white hover:bg-slate-800 dark:bg-cyan-400 dark:text-slate-950 dark:hover:bg-cyan-300"
|
|
||||||
>
|
|
||||||
<Link to="/">
|
|
||||||
<Home className="me-2 h-4 w-4" />
|
|
||||||
{isFa ? "بازگشت به خانه" : "Back home"}
|
|
||||||
</Link>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
asChild
|
|
||||||
variant="outline"
|
|
||||||
className="h-14 rounded-full border-slate-200 bg-white/85 px-7 text-base text-slate-800 shadow-sm backdrop-blur hover:bg-white dark:border-slate-800 dark:bg-slate-950/70 dark:text-slate-100 dark:hover:bg-slate-900"
|
|
||||||
>
|
|
||||||
<Link to="/about">
|
|
||||||
<Command className="me-2 h-4 w-4" />
|
|
||||||
{isFa ? "درباره Qlockify" : "About Qlockify"}
|
|
||||||
{isFa ? (
|
|
||||||
<ArrowLeft className="ms-2 h-4 w-4" />
|
|
||||||
) : (
|
|
||||||
<ArrowRight className={cn("ms-2 h-4 w-4")} />
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
<h1 className="mt-5 text-3xl font-semibold tracking-[-0.04em] sm:text-5xl">
|
||||||
</div>
|
{isFa ? "صفحه پیدا نشد" : "Page not found"}
|
||||||
|
</h1>
|
||||||
|
<p className="mx-auto mt-5 max-w-xl text-base leading-8 text-slate-600 sm:text-lg dark:text-slate-300">
|
||||||
|
{isFa
|
||||||
|
? "این صفحه وجود ندارد یا آدرس آن تغییر کرده است."
|
||||||
|
: "This page does not exist or its address has changed."}
|
||||||
|
</p>
|
||||||
|
<div className="mt-9 flex flex-col justify-center gap-3 sm:flex-row">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => navigate(-1)}
|
||||||
|
className="h-14 rounded-full border-slate-200 bg-white/80 px-7 text-base text-slate-800 backdrop-blur hover:bg-white dark:border-slate-800 dark:bg-slate-950/70 dark:text-slate-100 dark:hover:bg-slate-900"
|
||||||
|
>
|
||||||
|
{isFa ? <ArrowRight className="me-2 h-4 w-4" /> : <ArrowLeft className="me-2 h-4 w-4" />}
|
||||||
|
{isFa ? "بازگشت" : "Go back"}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
onClick={() => navigate("/")}
|
||||||
|
className="h-14 rounded-full bg-slate-950 px-7 text-base text-white hover:bg-slate-800 dark:bg-cyan-400 dark:text-slate-950 dark:hover:bg-cyan-300"
|
||||||
|
>
|
||||||
|
<Home className="me-2 h-4 w-4" />
|
||||||
|
{isFa ? "صفحه اصلی" : "Home page"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user