convert-next.js

This commit is contained in:
R-Bharathraj
2026-06-29 18:07:43 +05:30
parent 4760f8e063
commit 0140b0bdf8
1474 changed files with 16523 additions and 9272 deletions

View File

@@ -0,0 +1,268 @@
'use client';
import { useState, FormEvent } from 'react';
type FormState = 'idle' | 'sending' | 'success' | 'error';
const DETAILS = [
{
label: 'Visit us',
value: <>No.424, Red Rose Towers,<br />DB Road, RS Puram,<br />Coimbatore 641002</>,
icon: (
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z" /><circle cx="12" cy="10" r="3" />
</svg>
),
},
{
label: 'Email us',
value: <a href="mailto:loyalydigital@gmail.com" style={{ color: '#fff', textDecoration: 'none', fontWeight: 600 }}>loyalydigital@gmail.com</a>,
icon: (
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<rect x="2" y="4" width="20" height="16" rx="2" /><path d="m22 7-10 5L2 7" />
</svg>
),
},
];
const SOCIALS = [
{ label: 'LinkedIn', href: 'https://www.linkedin.com/company/loyaly-ai', icon: <svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M19.7 3H4.3C3.58 3 3 3.58 3 4.3v15.4C3 20.42 3.58 21 4.3 21h15.4c.72 0 1.3-.58 1.3-1.3V4.3C21 3.58 20.42 3 19.7 3zM8.34 18.34H5.67V9.75h2.67v8.59zM7 8.57a1.55 1.55 0 1 1 0-3.1 1.55 1.55 0 0 1 0 3.1zm11.34 9.77h-2.67v-4.18c0-1-.02-2.28-1.39-2.28-1.39 0-1.6 1.09-1.6 2.21v4.25h-2.67V9.75h2.56v1.17h.04c.36-.68 1.23-1.39 2.53-1.39 2.7 0 3.2 1.78 3.2 4.09v4.72z" /></svg> },
{ label: 'X / Twitter', href: 'https://twitter.com/loyalyai', icon: <svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M13.98 10.62 20.54 3h-1.55l-5.7 6.62L8.74 3H3.5l6.88 10.01L3.5 21h1.55l6.01-6.99L15.87 21h5.24l-7.13-10.38z" /></svg> },
{ label: 'Instagram', href: 'https://instagram.com/loyalyai', icon: <svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.16c3.2 0 3.58.01 4.85.07 3.25.15 4.77 1.69 4.92 4.92.06 1.27.07 1.65.07 4.85 0 3.2-.01 3.58-.07 4.85-.15 3.23-1.66 4.77-4.92 4.92-1.27.06-1.64.07-4.85.07-3.2 0-3.58-.01-4.85-.07-3.26-.15-4.77-1.7-4.92-4.92-.06-1.27-.07-1.64-.07-4.85 0-3.2.01-3.58.07-4.85.15-3.23 1.66-4.77 4.92-4.92C8.42 2.17 8.8 2.16 12 2.16zm0 1.62c-3.14 0-3.51.01-4.75.07-3.17.14-4.56 1.55-4.7 4.7-.06 1.24-.07 1.6-.07 4.75s.01 3.51.07 4.75c.14 3.15 1.53 4.56 4.7 4.7 1.24.06 1.61.07 4.75.07s3.51-.01 4.75-.07c3.17-.14 4.56-1.55 4.7-4.7.06-1.24.07-1.6.07-4.75s-.01-3.51-.07-4.75c-.14-3.15-1.53-4.56-4.7-4.7-1.24-.06-1.61-.07-4.75-.07zm0 4.32a5.74 5.74 0 100 11.48 5.74 5.74 0 000-11.48zm0 9.46a3.72 3.72 0 110-7.44 3.72 3.72 0 010 7.44zm5.96-9.65a1.34 1.34 0 11-2.68 0 1.34 1.34 0 012.68 0z" /></svg> },
];
export default function GetInTouch() {
const [formState, setFormState] = useState<FormState>('idle');
const [errorMessage, setErrorMessage] = useState('');
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
setFormState('sending');
setErrorMessage('');
const form = e.currentTarget;
const data = {
name: (form.elements.namedItem('name') as HTMLInputElement).value,
email: (form.elements.namedItem('email') as HTMLInputElement).value,
subject: (form.elements.namedItem('subject') as HTMLInputElement).value,
message: (form.elements.namedItem('message') as HTMLTextAreaElement).value,
};
try {
const res = await fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new Error(body.message || `Request failed: ${res.status}`);
}
setFormState('success');
form.reset();
} catch (err) {
setFormState('error');
setErrorMessage(err instanceof Error ? err.message : 'Something went wrong. Please try again.');
}
};
return (
<section
id="contact"
aria-label="Contact us"
style={{
position: 'relative',
margin: '0 20px 0',
borderRadius: '24px 24px 0 0',
overflow: 'hidden',
background: '#07070d',
}}
>
<div style={{
position: 'relative', zIndex: 2,
maxWidth: 1200, margin: '0 auto',
padding: 'clamp(56px, 8vh, 100px) clamp(28px, 5vw, 72px)',
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))',
gap: 'clamp(40px, 5vw, 80px)',
alignItems: 'start',
}}>
{/* ── Left — info ── */}
<div>
<div style={{
fontSize: 11, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase',
color: '#f4be28', fontFamily: 'Manrope, sans-serif', marginBottom: 24,
display: 'flex', alignItems: 'center', gap: 12,
}}>
<span style={{ width: 28, height: 1, background: '#f4be28', display: 'block' }} />Get in Touch
</div>
<h2 style={{
margin: '0 0 24px',
fontSize: 'clamp(2rem, 4vw, 3.4rem)', fontWeight: 900,
lineHeight: 0.98, letterSpacing: '-0.04em',
color: '#fff', fontFamily: 'Sora, sans-serif',
}}>
Let's talk<br /><span style={{ color: '#f4be28' }}>strategy.</span>
</h2>
<p style={{
margin: '0 0 44px', fontSize: 16, lineHeight: 1.8,
color: 'rgba(255,255,255,0.42)', fontFamily: 'Manrope, sans-serif', maxWidth: 380,
}}>
Whether you're exploring AI possibilities or ready to deploy, our team will help you find the right solution for your business.
</p>
{/* Detail cards */}
<div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginBottom: 36 }}>
{DETAILS.map((d) => (
<div key={d.label} style={{
display: 'flex', gap: 16, alignItems: 'flex-start',
padding: '18px 20px', borderRadius: 16,
background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.07)',
}}>
<div style={{
width: 40, height: 40, borderRadius: 11, flexShrink: 0,
display: 'flex', alignItems: 'center', justifyContent: 'center',
background: 'rgba(244,190,40,0.1)', border: '1px solid rgba(244,190,40,0.22)',
color: '#f4be28',
}}>{d.icon}</div>
<div>
<div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.4)', fontFamily: 'Manrope, sans-serif', marginBottom: 6 }}>{d.label}</div>
<div style={{ fontSize: 15, lineHeight: 1.6, color: 'rgba(255,255,255,0.7)', fontFamily: 'Manrope, sans-serif' }}>{d.value}</div>
</div>
</div>
))}
</div>
{/* Socials */}
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.35)', fontFamily: 'Manrope, sans-serif' }}>Follow</span>
{SOCIALS.map((s) => (
<a key={s.label} href={s.href} target="_blank" rel="noopener noreferrer" aria-label={s.label} className="git-social">
{s.icon}
</a>
))}
</div>
</div>
{/* ── Right — form ── */}
<div style={{
background: 'rgba(255,255,255,0.03)',
border: '1px solid rgba(255,255,255,0.08)',
borderRadius: 24,
padding: 'clamp(28px, 3vw, 44px)',
backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(20px)',
boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.05)',
}}>
{formState === 'success' ? (
<div role="status" aria-live="polite" style={{ textAlign: 'center', padding: '40px 0' }}>
<div style={{
width: 64, height: 64, borderRadius: '50%', margin: '0 auto 24px',
display: 'flex', alignItems: 'center', justifyContent: 'center',
background: 'rgba(74,222,128,0.12)', border: '1px solid rgba(74,222,128,0.3)',
}}>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#4ade80" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6 9 17l-5-5" /></svg>
</div>
<h3 style={{ margin: '0 0 10px', fontSize: 22, fontWeight: 800, color: '#fff', fontFamily: 'Sora, sans-serif', letterSpacing: '-0.02em' }}>Message sent!</h3>
<p style={{ margin: 0, color: 'rgba(255,255,255,0.45)', fontFamily: 'Manrope, sans-serif' }}>We'll get back to you within one business day.</p>
<button onClick={() => setFormState('idle')} style={{
marginTop: 28, padding: '12px 28px', borderRadius: 100,
background: 'transparent', border: '1px solid rgba(255,255,255,0.2)',
color: '#fff', fontWeight: 600, fontSize: 14, cursor: 'pointer',
fontFamily: 'Manrope, sans-serif',
}}>Send another message</button>
</div>
) : (
<form onSubmit={handleSubmit} noValidate>
<h3 style={{ margin: '0 0 28px', fontSize: 22, fontWeight: 800, color: '#fff', fontFamily: 'Sora, sans-serif', letterSpacing: '-0.02em' }}>
Send us a message
</h3>
{formState === 'error' && (
<div role="alert" style={{
marginBottom: 20, padding: '12px 16px',
background: 'rgba(248,113,113,0.1)', border: '1px solid rgba(248,113,113,0.3)',
color: '#fca5a5', borderRadius: 12, fontSize: 14, fontFamily: 'Manrope, sans-serif',
}}>{errorMessage}</div>
)}
<div style={{ display: 'grid', gap: 18 }}>
<label style={labelStyle}>
Full Name
<input type="text" name="name" required placeholder="Jane Smith" className="git-input" style={inputStyle} />
</label>
<label style={labelStyle}>
Email Address <span aria-hidden="true" style={{ color: '#f4be28' }}>*</span>
<input type="email" name="email" required placeholder="jane@company.com" className="git-input" style={inputStyle} />
</label>
<label style={labelStyle}>
Subject
<input type="text" name="subject" placeholder="How can we help?" className="git-input" style={inputStyle} />
</label>
<label style={labelStyle}>
Message
<textarea name="message" rows={5} placeholder="Tell us about your business and what you're trying to achieve" className="git-input" style={{ ...inputStyle, resize: 'vertical', minHeight: 120 }} />
</label>
<button type="submit" disabled={formState === 'sending'} style={{
marginTop: 4, padding: '16px 28px', borderRadius: 100, border: 'none',
background: formState === 'sending' ? 'rgba(244,190,40,0.6)' : '#f4be28',
color: '#111', fontWeight: 800, fontSize: 15, fontFamily: 'Manrope, sans-serif',
cursor: formState === 'sending' ? 'wait' : 'pointer',
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
boxShadow: '0 12px 36px rgba(244,190,40,0.25)',
transition: 'transform 0.25s ease',
}}>
{formState === 'sending' ? (
<>
<span style={{ display: 'inline-block', width: 16, height: 16, border: '2px solid #111', borderTopColor: 'transparent', borderRadius: '50%', animation: 'gitspin 0.7s linear infinite' }} aria-hidden="true" />
Sending…
</>
) : (
<>Send Message <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6" /></svg></>
)}
</button>
</div>
</form>
)}
</div>
</div>
<style>{`
@keyframes gitspin { to { transform: rotate(360deg); } }
.git-input::placeholder { color: rgba(255,255,255,0.3); }
.git-input:focus { border-color: rgba(244,190,40,0.6) !important; box-shadow: 0 0 0 3px rgba(244,190,40,0.12) !important; }
.git-social {
width: 38px; height: 38px; border-radius: 10px;
display: flex; align-items: center; justify-content: center;
background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.08);
color: rgba(255,255,255,0.5); transition: all 0.2s ease;
}
.git-social:hover { background: rgba(244,190,40,0.12); border-color: rgba(244,190,40,0.3); color: #f4be28; }
`}</style>
</section>
);
}
const labelStyle: React.CSSProperties = {
display: 'flex', flexDirection: 'column', gap: 8,
fontSize: 13, fontWeight: 600, color: 'rgba(255,255,255,0.55)',
fontFamily: 'Manrope, sans-serif',
};
const inputStyle: React.CSSProperties = {
padding: '13px 16px',
border: '1px solid rgba(255,255,255,0.1)',
borderRadius: 12,
fontSize: 15,
background: 'rgba(255,255,255,0.04)',
color: '#fff',
outline: 'none',
width: '100%',
boxSizing: 'border-box',
fontFamily: 'Manrope, sans-serif',
transition: 'border-color 0.2s ease, box-shadow 0.2s ease',
};