514 lines
26 KiB
TypeScript
514 lines
26 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useRef, useState } from 'react';
|
|
import Navigation from '../../../components/Navigation';
|
|
import FloatingLanguageSwitcher from '../../../components/FloatingLanguageSwitcher';
|
|
import Footer from '../../../components/Footer';
|
|
import { Locale } from '../../../lib/i18n';
|
|
import { getTranslations } from '../../../lib/translations';
|
|
import { updateDocumentMeta } from '../../../lib/seo-utils';
|
|
|
|
// Arctic Particle Background Component
|
|
function ArcticParticleBackground() {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
|
|
useEffect(() => {
|
|
const canvas = canvasRef.current;
|
|
if (!canvas) return;
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
if (!ctx) return;
|
|
|
|
// Set canvas size
|
|
const resizeCanvas = () => {
|
|
canvas.width = window.innerWidth;
|
|
canvas.height = window.innerHeight;
|
|
};
|
|
resizeCanvas();
|
|
window.addEventListener('resize', resizeCanvas);
|
|
|
|
// Particle system for arctic theme
|
|
const particles: Array<{
|
|
x: number;
|
|
y: number;
|
|
vx: number;
|
|
vy: number;
|
|
size: number;
|
|
opacity: number;
|
|
type: 'snow' | 'ice' | 'aurora';
|
|
}> = [];
|
|
|
|
// Create particles
|
|
for (let i = 0; i < 150; i++) {
|
|
const type = Math.random() < 0.7 ? 'snow' : Math.random() < 0.9 ? 'ice' : 'aurora';
|
|
particles.push({
|
|
x: Math.random() * canvas.width,
|
|
y: Math.random() * canvas.height,
|
|
vx: (Math.random() - 0.5) * (type === 'snow' ? 0.3 : 0.1),
|
|
vy: type === 'snow' ? Math.random() * 0.5 + 0.2 : (Math.random() - 0.5) * 0.1,
|
|
size:
|
|
type === 'snow'
|
|
? Math.random() * 3 + 1
|
|
: type === 'ice'
|
|
? Math.random() * 2 + 0.5
|
|
: Math.random() * 4 + 2,
|
|
opacity: type === 'aurora' ? Math.random() * 0.3 + 0.1 : Math.random() * 0.6 + 0.2,
|
|
type,
|
|
});
|
|
}
|
|
|
|
// Animation loop
|
|
const animate = () => {
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
particles.forEach((particle) => {
|
|
// Update position
|
|
particle.x += particle.vx;
|
|
particle.y += particle.vy;
|
|
|
|
// Wrap around edges
|
|
if (particle.x < -10) particle.x = canvas.width + 10;
|
|
if (particle.x > canvas.width + 10) particle.x = -10;
|
|
if (particle.y < -10) particle.y = canvas.height + 10;
|
|
if (particle.y > canvas.height + 10) particle.y = -10;
|
|
|
|
// Draw particle based on type
|
|
ctx.beginPath();
|
|
|
|
if (particle.type === 'snow') {
|
|
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
|
|
ctx.fillStyle = `rgba(255, 255, 255, ${particle.opacity})`;
|
|
ctx.fill();
|
|
} else if (particle.type === 'ice') {
|
|
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
|
|
ctx.fillStyle = `rgba(173, 216, 230, ${particle.opacity})`;
|
|
ctx.fill();
|
|
} else if (particle.type === 'aurora') {
|
|
const gradient = ctx.createRadialGradient(
|
|
particle.x,
|
|
particle.y,
|
|
0,
|
|
particle.x,
|
|
particle.y,
|
|
particle.size * 3,
|
|
);
|
|
gradient.addColorStop(0, `rgba(0, 255, 150, ${particle.opacity})`);
|
|
gradient.addColorStop(0.5, `rgba(0, 150, 255, ${particle.opacity * 0.5})`);
|
|
gradient.addColorStop(1, `rgba(150, 0, 255, 0)`);
|
|
|
|
ctx.arc(particle.x, particle.y, particle.size * 3, 0, Math.PI * 2);
|
|
ctx.fillStyle = gradient;
|
|
ctx.fill();
|
|
}
|
|
});
|
|
|
|
// Draw connections between ice particles
|
|
particles
|
|
.filter((p) => p.type === 'ice')
|
|
.forEach((particle, i, iceParticles) => {
|
|
iceParticles.slice(i + 1).forEach((otherParticle) => {
|
|
const dx = particle.x - otherParticle.x;
|
|
const dy = particle.y - otherParticle.y;
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
if (distance < 80) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(particle.x, particle.y);
|
|
ctx.lineTo(otherParticle.x, otherParticle.y);
|
|
ctx.strokeStyle = `rgba(173, 216, 230, ${0.1 * (1 - distance / 80)})`;
|
|
ctx.lineWidth = 1;
|
|
ctx.stroke();
|
|
}
|
|
});
|
|
});
|
|
|
|
requestAnimationFrame(animate);
|
|
};
|
|
|
|
animate();
|
|
|
|
return () => {
|
|
window.removeEventListener('resize', resizeCanvas);
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<canvas
|
|
ref={canvasRef}
|
|
className="absolute inset-0 w-full h-full"
|
|
style={{ pointerEvents: 'none' }}
|
|
data-oid="vdts.76"
|
|
/>
|
|
);
|
|
}
|
|
|
|
export default function ContactPage({ params }: { params: { locale: Locale } }) {
|
|
const t = getTranslations(params.locale);
|
|
const [formData, setFormData] = useState({
|
|
firstName: '',
|
|
lastName: '',
|
|
email: '',
|
|
phone: '',
|
|
message: '',
|
|
});
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const [submitStatus, setSubmitStatus] = useState<'idle' | 'success' | 'error'>('idle');
|
|
|
|
// Update meta tags when locale changes
|
|
useEffect(() => {
|
|
updateDocumentMeta(params.locale);
|
|
}, [params.locale]);
|
|
|
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
const { name, value } = e.target;
|
|
setFormData((prev) => ({
|
|
...prev,
|
|
[name]: value,
|
|
}));
|
|
};
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setIsSubmitting(true);
|
|
|
|
// Simulate form submission
|
|
try {
|
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
setSubmitStatus('success');
|
|
setFormData({
|
|
firstName: '',
|
|
lastName: '',
|
|
email: '',
|
|
phone: '',
|
|
message: '',
|
|
});
|
|
} catch (error) {
|
|
setSubmitStatus('error');
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
setTimeout(() => setSubmitStatus('idle'), 5000);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen relative overflow-hidden" data-oid="cxtwh67">
|
|
{/* Arctic Background with Overlay */}
|
|
<div
|
|
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
|
style={{
|
|
backgroundImage: `linear-gradient(rgba(0, 50, 100, 0.7), rgba(0, 30, 60, 0.8)), url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800"><defs><linearGradient id="arctic1" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:%2387CEEB;stop-opacity:1" /><stop offset="50%" style="stop-color:%234682B4;stop-opacity:1" /><stop offset="100%" style="stop-color:%23191970;stop-opacity:1" /></linearGradient></defs><rect width="1200" height="800" fill="url(%23arctic1)"/><path d="M0,600 Q300,500 600,550 T1200,500 L1200,800 L0,800 Z" fill="%23F0F8FF"/><path d="M0,650 Q400,580 800,620 T1200,600 L1200,800 L0,800 Z" fill="%23E6F3FF"/><ellipse cx="200" cy="200" rx="60" ry="30" fill="%23FFFFFF" opacity="0.8"/><ellipse cx="800" cy="150" rx="80" ry="40" fill="%23FFFFFF" opacity="0.6"/><ellipse cx="1000" cy="250" rx="50" ry="25" fill="%23FFFFFF" opacity="0.7"/></svg>')`,
|
|
}}
|
|
data-oid="g8y9fqe"
|
|
/>
|
|
|
|
{/* Arctic Particle Background */}
|
|
<ArcticParticleBackground data-oid="cn3_8yw" />
|
|
|
|
{/* Navigation */}
|
|
<Navigation locale={params.locale} data-oid="88otgww" />
|
|
|
|
{/* Floating Language Switcher */}
|
|
<FloatingLanguageSwitcher locale={params.locale} data-oid="lzqtg48" />
|
|
|
|
{/* Contact Section */}
|
|
<section className="relative z-10 py-20 px-4" data-oid="wlyxybl">
|
|
<div className="max-w-6xl mx-auto" data-oid="8rk2.0s">
|
|
{/* Header */}
|
|
<div className="text-center mb-16" data-oid="q1kwgw8">
|
|
<h1
|
|
className="text-5xl md:text-6xl font-bold text-white mb-6 leading-tight"
|
|
data-oid="ek48zik"
|
|
>
|
|
{t.contact.title}
|
|
</h1>
|
|
<p
|
|
className="text-xl md:text-2xl text-white/90 max-w-3xl mx-auto leading-relaxed"
|
|
data-oid="1k-t_ie"
|
|
>
|
|
{t.contact.subtitle}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12" data-oid="_xqiofz">
|
|
{/* Contact Form */}
|
|
<div
|
|
className="bg-white/10 backdrop-blur-md rounded-3xl p-8 border border-white/20 shadow-2xl"
|
|
data-oid="pkudnst"
|
|
>
|
|
<form onSubmit={handleSubmit} className="space-y-6" data-oid="dcdmf-y">
|
|
{/* Name Fields */}
|
|
<div
|
|
className="grid grid-cols-1 md:grid-cols-2 gap-4"
|
|
data-oid="p34ti:p"
|
|
>
|
|
<div data-oid="u_cyg_s">
|
|
<input
|
|
type="text"
|
|
name="firstName"
|
|
value={formData.firstName}
|
|
onChange={handleInputChange}
|
|
placeholder={t.contact.form.firstName}
|
|
required
|
|
className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-white/70 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all duration-200"
|
|
data-oid="-mrpkhk"
|
|
/>
|
|
</div>
|
|
<div data-oid="q:lwf4n">
|
|
<input
|
|
type="text"
|
|
name="lastName"
|
|
value={formData.lastName}
|
|
onChange={handleInputChange}
|
|
placeholder={t.contact.form.lastName}
|
|
required
|
|
className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-white/70 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all duration-200"
|
|
data-oid="s6mgi:f"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Email and Phone */}
|
|
<div
|
|
className="grid grid-cols-1 md:grid-cols-2 gap-4"
|
|
data-oid="qlzghax"
|
|
>
|
|
<div data-oid="9eu.6rr">
|
|
<input
|
|
type="email"
|
|
name="email"
|
|
value={formData.email}
|
|
onChange={handleInputChange}
|
|
placeholder={t.contact.form.email}
|
|
required
|
|
className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-white/70 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all duration-200"
|
|
data-oid="0fgza5i"
|
|
/>
|
|
</div>
|
|
<div data-oid="d8--iet">
|
|
<input
|
|
type="tel"
|
|
name="phone"
|
|
value={formData.phone}
|
|
onChange={handleInputChange}
|
|
placeholder={t.contact.form.phone}
|
|
className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-white/70 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all duration-200"
|
|
data-oid="wwwvzhx"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Message */}
|
|
<div data-oid="59jnejx">
|
|
<textarea
|
|
name="message"
|
|
value={formData.message}
|
|
onChange={handleInputChange}
|
|
placeholder={t.contact.form.message}
|
|
required
|
|
rows={6}
|
|
className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-white/70 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all duration-200 resize-none"
|
|
data-oid="u:fwgn0"
|
|
/>
|
|
</div>
|
|
|
|
{/* Submit Button */}
|
|
<div data-oid="rh_o0-0">
|
|
<button
|
|
type="submit"
|
|
disabled={isSubmitting}
|
|
className={`w-full py-4 px-8 rounded-xl font-semibold text-lg transition-all duration-200 transform hover:scale-105 ${
|
|
isSubmitting
|
|
? 'bg-gray-500 cursor-not-allowed'
|
|
: submitStatus === 'success'
|
|
? 'bg-green-500 hover:bg-green-600'
|
|
: submitStatus === 'error'
|
|
? 'bg-red-500 hover:bg-red-600'
|
|
: 'bg-blue-500 hover:bg-blue-600'
|
|
} text-white shadow-lg`}
|
|
data-oid="l.p.45q"
|
|
>
|
|
{isSubmitting
|
|
? 'Sending...'
|
|
: submitStatus === 'success'
|
|
? 'Message Sent!'
|
|
: submitStatus === 'error'
|
|
? 'Try Again'
|
|
: t.contact.form.send}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
{/* Contact Information */}
|
|
<div className="space-y-8" data-oid="gcnlszq">
|
|
<div
|
|
className="bg-white/10 backdrop-blur-md rounded-3xl p-8 border border-white/20 shadow-2xl"
|
|
data-oid="dk_e_44"
|
|
>
|
|
<h3
|
|
className="text-2xl font-bold text-white mb-6"
|
|
data-oid="p5r03zc"
|
|
>
|
|
{t.contact.info.title}
|
|
</h3>
|
|
<p
|
|
className="text-white/90 mb-8 leading-relaxed"
|
|
data-oid="b3:lk4-"
|
|
>
|
|
{t.contact.info.description}
|
|
</p>
|
|
|
|
<div className="space-y-6" data-oid="hl4u4je">
|
|
{/* Email */}
|
|
<div className="flex items-center space-x-4" data-oid="g4na330">
|
|
<div
|
|
className="w-12 h-12 bg-blue-500/20 rounded-full flex items-center justify-center"
|
|
data-oid="kl7x59e"
|
|
>
|
|
<svg
|
|
className="w-6 h-6 text-blue-400"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
data-oid="runsvm_"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
|
data-oid="ccc37jv"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<div data-oid="9kfzma8">
|
|
<p className="text-white/70 text-sm" data-oid="vk.z7te">
|
|
Email
|
|
</p>
|
|
<p
|
|
className="text-white font-medium"
|
|
data-oid="mk6ei1x"
|
|
>
|
|
{t.contact.info.email}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Phone */}
|
|
<div className="flex items-center space-x-4" data-oid=".1a0g8l">
|
|
<div
|
|
className="w-12 h-12 bg-green-500/20 rounded-full flex items-center justify-center"
|
|
data-oid="4m5q0ec"
|
|
>
|
|
<svg
|
|
className="w-6 h-6 text-green-400"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
data-oid="8amai42"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"
|
|
data-oid="7oc0h_5"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<div data-oid="knv5:6o">
|
|
<p className="text-white/70 text-sm" data-oid=".:vq7ax">
|
|
Phone
|
|
</p>
|
|
<p
|
|
className="text-white font-medium"
|
|
data-oid="3wxvnf4"
|
|
>
|
|
{t.contact.info.phone}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Address */}
|
|
<div className="flex items-center space-x-4" data-oid="0is872f">
|
|
<div
|
|
className="w-12 h-12 bg-purple-500/20 rounded-full flex items-center justify-center"
|
|
data-oid="s:hqv83"
|
|
>
|
|
<svg
|
|
className="w-6 h-6 text-purple-400"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
data-oid="svaynoq"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
|
|
data-oid="i1luz2w"
|
|
/>
|
|
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
|
data-oid="c0qo67."
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<div data-oid="nf5h5sm">
|
|
<p className="text-white/70 text-sm" data-oid="uramiy4">
|
|
Address
|
|
</p>
|
|
<p
|
|
className="text-white font-medium"
|
|
data-oid="k56c61v"
|
|
>
|
|
{t.contact.info.address}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Additional Info Card */}
|
|
<div
|
|
className="bg-gradient-to-br from-blue-500/20 to-purple-500/20 backdrop-blur-md rounded-3xl p-8 border border-white/20 shadow-2xl"
|
|
data-oid="_.1cxld"
|
|
>
|
|
<h4
|
|
className="text-xl font-bold text-white mb-4"
|
|
data-oid="m83e9xn"
|
|
>
|
|
Response Time
|
|
</h4>
|
|
<p className="text-white/90 mb-4" data-oid="tjr_3e3">
|
|
We typically respond within 24 hours during business days.
|
|
</p>
|
|
<div className="flex items-center space-x-2" data-oid="ooel29n">
|
|
<div
|
|
className="w-3 h-3 bg-green-400 rounded-full animate-pulse"
|
|
data-oid="5l9ximw"
|
|
></div>
|
|
<span
|
|
className="text-green-400 text-sm font-medium"
|
|
data-oid="l6d:_3y"
|
|
>
|
|
Online Now
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Footer */}
|
|
<Footer locale={params.locale} data-oid="t66xypj" />
|
|
</div>
|
|
);
|
|
}
|