- Convert site from royal-blue theme to black/white monochrome (desaturate all blue-hued colors; keep WhatsApp green and error red) - Swap blue circular brand logo for mono YS mark; regenerate favicon/PWA icons - Add 6 Pudu robots (CC1 Pro, MT1 Max, MT1 Vac, T600, T600 Underride, BG1 Pro) - Fix favicon.ico to RGBA (Next 16 Turbopack decode) and Stripe apiVersion type Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
151 lines
6.6 KiB
TypeScript
151 lines
6.6 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import { CATEGORY_LABELS, type RobotCategory } from '@/data/robots';
|
|
|
|
type Props = {
|
|
defaultRobot?: string;
|
|
defaultCategory?: RobotCategory | '';
|
|
intent?: 'inquiry' | 'demo' | 'quotation';
|
|
};
|
|
|
|
const INTENT_LABEL: Record<NonNullable<Props['intent']>, string> = {
|
|
inquiry: 'Send inquiry',
|
|
demo: 'Book live demo',
|
|
quotation: 'Request quotation',
|
|
};
|
|
|
|
export function InquiryForm({ defaultRobot = '', defaultCategory = '', intent = 'inquiry' }: Props) {
|
|
const [data, setData] = useState({
|
|
name: '',
|
|
company: '',
|
|
email: '',
|
|
phone: '',
|
|
robotInterest: defaultRobot,
|
|
category: defaultCategory as string,
|
|
message: '',
|
|
});
|
|
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
|
|
|
|
const onSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setStatus('loading');
|
|
try {
|
|
const res = await fetch('/api/contact', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
name: data.name,
|
|
email: data.email,
|
|
phone: data.phone,
|
|
message:
|
|
`[${intent.toUpperCase()}] from ${data.company || 'Individual'}\n` +
|
|
`Robot interest: ${data.robotInterest || 'N/A'}\n` +
|
|
`Category: ${data.category || 'N/A'}\n\n` +
|
|
data.message,
|
|
}),
|
|
});
|
|
if (res.ok) {
|
|
setStatus('success');
|
|
setData({ name: '', company: '', email: '', phone: '', robotInterest: defaultRobot, category: defaultCategory as string, message: '' });
|
|
setTimeout(() => setStatus('idle'), 4500);
|
|
} else {
|
|
setStatus('error');
|
|
setTimeout(() => setStatus('idle'), 4500);
|
|
}
|
|
} catch {
|
|
setStatus('error');
|
|
setTimeout(() => setStatus('idle'), 4500);
|
|
}
|
|
};
|
|
|
|
const field: React.CSSProperties = {
|
|
width: '100%',
|
|
padding: '0.875rem 1rem',
|
|
borderRadius: '0.75rem',
|
|
border: '1px solid rgba(94, 94, 94, 0.18)',
|
|
background: 'rgba(15, 12, 8,0.55)',
|
|
color: '#fcfcfc',
|
|
fontSize: '0.95rem',
|
|
outline: 'none',
|
|
boxSizing: 'border-box',
|
|
transition: 'border-color 0.2s, background 0.2s',
|
|
fontFamily: 'inherit',
|
|
};
|
|
|
|
const label: React.CSSProperties = {
|
|
fontSize: '0.72rem',
|
|
letterSpacing: '0.18em',
|
|
textTransform: 'uppercase',
|
|
color: '#a8a8a8',
|
|
fontWeight: 600,
|
|
};
|
|
|
|
return (
|
|
<form onSubmit={onSubmit} style={{ display: 'grid', gap: '1rem' }}>
|
|
{status === 'success' && (
|
|
<div style={{ padding: '0.875rem 1rem', borderRadius: 12, background: 'rgba(34,197,94,0.1)', border: '1px solid rgba(34,197,94,0.3)', color: '#86efac' }}>
|
|
Thank you your message was sent. Our team will reach out shortly.
|
|
</div>
|
|
)}
|
|
{status === 'error' && (
|
|
<div style={{ padding: '0.875rem 1rem', borderRadius: 12, background: 'rgba(239,68,68,0.1)', border: '1px solid rgba(239,68,68,0.3)', color: '#fca5a5' }}>
|
|
Something went wrong. Please try again, or email info@yslootahrobotics.com.
|
|
</div>
|
|
)}
|
|
|
|
<div style={{ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(auto-fit, minmax(min(220px, 100%), 1fr))' }}>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
<label style={label} htmlFor="i-name">Full name</label>
|
|
<input id="i-name" required style={field} value={data.name} onChange={(e) => setData({ ...data, name: e.target.value })} placeholder="Your name" />
|
|
</div>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
<label style={label} htmlFor="i-company">Company</label>
|
|
<input id="i-company" style={field} value={data.company} onChange={(e) => setData({ ...data, company: e.target.value })} placeholder="Company or organization" />
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(auto-fit, minmax(min(220px, 100%), 1fr))' }}>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
<label style={label} htmlFor="i-email">Email</label>
|
|
<input id="i-email" type="email" required style={field} value={data.email} onChange={(e) => setData({ ...data, email: e.target.value })} placeholder="you@company.com" />
|
|
</div>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
<label style={label} htmlFor="i-phone">Phone / WhatsApp</label>
|
|
<input id="i-phone" style={field} value={data.phone} onChange={(e) => setData({ ...data, phone: e.target.value })} placeholder="+971 …" />
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(auto-fit, minmax(min(220px, 100%), 1fr))' }}>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
<label style={label} htmlFor="i-robot">Robot of interest</label>
|
|
<input id="i-robot" style={field} value={data.robotInterest} onChange={(e) => setData({ ...data, robotInterest: e.target.value })} placeholder="e.g. Unitree Go2, BellaBot" />
|
|
</div>
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
<label style={label} htmlFor="i-cat">Preferred category</label>
|
|
<select id="i-cat" style={field} value={data.category} onChange={(e) => setData({ ...data, category: e.target.value })}>
|
|
<option value="">Select a category</option>
|
|
{(Object.keys(CATEGORY_LABELS) as RobotCategory[]).map((c) => (
|
|
<option key={c} value={c}>{CATEGORY_LABELS[c]}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
<label style={label} htmlFor="i-msg">Project details</label>
|
|
<textarea id="i-msg" required rows={4} style={{ ...field, resize: 'vertical', fontFamily: 'inherit' }} value={data.message} onChange={(e) => setData({ ...data, message: e.target.value })} placeholder="Tell us about your use case, timeline, and venue." />
|
|
</div>
|
|
|
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem', alignItems: 'center', marginTop: '0.25rem' }}>
|
|
<button type="submit" disabled={status === 'loading'} className="btn btn-primary" style={{ opacity: status === 'loading' ? 0.6 : 1, cursor: status === 'loading' ? 'wait' : 'pointer' }}>
|
|
{status === 'loading' ? 'Sending…' : INTENT_LABEL[intent]}
|
|
</button>
|
|
<a href="https://wa.me/971559482728" target="_blank" rel="noopener noreferrer" className="btn btn-ghost">
|
|
WhatsApp us
|
|
</a>
|
|
</div>
|
|
</form>
|
|
);
|
|
}
|