- Frontend: Next.js 14 with TypeScript - Backend: FastAPI with SQLAlchemy - Agent: Carmodoo sync agent - Deployment: Docker Compose based staging/production setup - Scripts: Automated deployment with rollback support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
611 lines
29 KiB
TypeScript
611 lines
29 KiB
TypeScript
'use client';
|
||
|
||
import { useState, useEffect } from 'react';
|
||
import { useTranslation } from '@/lib/i18n';
|
||
import { useAuthStore } from '@/lib/store';
|
||
import { inquiryApi, Inquiry, InquiryWithMessages } from '@/lib/api';
|
||
|
||
const CATEGORY_LABELS: Record<string, Record<string, string>> = {
|
||
ko: {
|
||
general: '일반 문의',
|
||
vehicle: '차량 문의',
|
||
payment: '결제 문의',
|
||
shipping: '배송 문의',
|
||
dealer: '딜러 문의',
|
||
account: '계정 문의',
|
||
other: '기타',
|
||
},
|
||
en: {
|
||
general: 'General',
|
||
vehicle: 'Vehicle',
|
||
payment: 'Payment',
|
||
shipping: 'Shipping',
|
||
dealer: 'Dealer',
|
||
account: 'Account',
|
||
other: 'Other',
|
||
},
|
||
};
|
||
|
||
const STATUS_LABELS: Record<string, Record<string, string>> = {
|
||
ko: {
|
||
pending: '대기중',
|
||
in_progress: '처리중',
|
||
resolved: '해결됨',
|
||
closed: '종료',
|
||
},
|
||
en: {
|
||
pending: 'Pending',
|
||
in_progress: 'In Progress',
|
||
resolved: 'Resolved',
|
||
closed: 'Closed',
|
||
},
|
||
};
|
||
|
||
const STATUS_COLORS: Record<string, string> = {
|
||
pending: 'bg-yellow-100 text-yellow-800',
|
||
in_progress: 'bg-blue-100 text-blue-800',
|
||
resolved: 'bg-green-100 text-green-800',
|
||
closed: 'bg-gray-100 text-gray-800',
|
||
};
|
||
|
||
export default function ContactPage() {
|
||
const { t, language } = useTranslation();
|
||
const { user } = useAuthStore();
|
||
|
||
const [formData, setFormData] = useState({
|
||
name: '',
|
||
email: '',
|
||
phone: '',
|
||
category: 'general',
|
||
subject: '',
|
||
message: '',
|
||
});
|
||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||
const [isSubmitted, setIsSubmitted] = useState(false);
|
||
const [error, setError] = useState('');
|
||
|
||
// Inquiry history state
|
||
const [myInquiries, setMyInquiries] = useState<Inquiry[]>([]);
|
||
const [loadingInquiries, setLoadingInquiries] = useState(false);
|
||
const [selectedInquiry, setSelectedInquiry] = useState<InquiryWithMessages | null>(null);
|
||
const [showDetailModal, setShowDetailModal] = useState(false);
|
||
const [replyMessage, setReplyMessage] = useState('');
|
||
const [sendingReply, setSendingReply] = useState(false);
|
||
const [activeTab, setActiveTab] = useState<'form' | 'history'>('form');
|
||
|
||
// Fetch user's inquiries
|
||
useEffect(() => {
|
||
if (user) {
|
||
fetchMyInquiries();
|
||
}
|
||
}, [user]);
|
||
|
||
const fetchMyInquiries = async () => {
|
||
setLoadingInquiries(true);
|
||
try {
|
||
const response = await inquiryApi.getMyInquiries(1, 50);
|
||
setMyInquiries(response.inquiries);
|
||
} catch (error) {
|
||
console.error('Failed to fetch inquiries:', error);
|
||
} finally {
|
||
setLoadingInquiries(false);
|
||
}
|
||
};
|
||
|
||
const handleSubmit = async (e: React.FormEvent) => {
|
||
e.preventDefault();
|
||
setIsSubmitting(true);
|
||
setError('');
|
||
|
||
try {
|
||
await inquiryApi.createInquiry({
|
||
category: formData.category,
|
||
subject: formData.subject || `${CATEGORY_LABELS[language]?.[formData.category] || formData.category} ${language === 'ko' ? '문의' : 'Inquiry'}`,
|
||
message: formData.message,
|
||
contact_email: formData.email || user?.email,
|
||
contact_phone: formData.phone || user?.phone,
|
||
});
|
||
|
||
setIsSubmitted(true);
|
||
setFormData({ name: '', email: '', phone: '', category: 'general', subject: '', message: '' });
|
||
|
||
if (user) {
|
||
fetchMyInquiries();
|
||
}
|
||
} catch (err: any) {
|
||
console.error('Failed to submit inquiry:', err);
|
||
setError(language === 'ko' ? '문의 등록에 실패했습니다. 다시 시도해주세요.' : 'Failed to submit inquiry. Please try again.');
|
||
} finally {
|
||
setIsSubmitting(false);
|
||
}
|
||
};
|
||
|
||
const openInquiryDetail = async (inquiry: Inquiry) => {
|
||
try {
|
||
const detail = await inquiryApi.getInquiryDetail(inquiry.id);
|
||
setSelectedInquiry(detail);
|
||
setShowDetailModal(true);
|
||
} catch (error) {
|
||
console.error('Failed to fetch inquiry detail:', error);
|
||
}
|
||
};
|
||
|
||
const handleSendReply = async () => {
|
||
if (!selectedInquiry || !replyMessage.trim()) return;
|
||
|
||
setSendingReply(true);
|
||
try {
|
||
await inquiryApi.addMessage(selectedInquiry.inquiry.id, replyMessage.trim());
|
||
const detail = await inquiryApi.getInquiryDetail(selectedInquiry.inquiry.id);
|
||
setSelectedInquiry(detail);
|
||
setReplyMessage('');
|
||
} catch (error) {
|
||
console.error('Failed to send reply:', error);
|
||
} finally {
|
||
setSendingReply(false);
|
||
}
|
||
};
|
||
|
||
const formatDate = (dateString: string) => {
|
||
return new Date(dateString).toLocaleDateString(language === 'ko' ? 'ko-KR' : 'en-US', {
|
||
year: 'numeric',
|
||
month: 'short',
|
||
day: 'numeric',
|
||
hour: '2-digit',
|
||
minute: '2-digit'
|
||
});
|
||
};
|
||
|
||
const categoryLabels = CATEGORY_LABELS[language] || CATEGORY_LABELS.en;
|
||
const statusLabels = STATUS_LABELS[language] || STATUS_LABELS.en;
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gray-50">
|
||
{/* Hero Section */}
|
||
<section className="bg-gradient-to-r from-primary-700 to-primary-900 text-white py-16">
|
||
<div className="container mx-auto px-4 text-center">
|
||
<h1 className="text-4xl md:text-5xl font-bold mb-4">{t.contactUs}</h1>
|
||
<p className="text-xl text-primary-100 max-w-2xl mx-auto">
|
||
{language === 'ko' ? '궁금한 점이 있으시면 언제든지 문의해 주세요' : 'Feel free to contact us anytime'}
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
<div className="container mx-auto px-4 py-12">
|
||
{/* Tabs for logged in users */}
|
||
{user && (
|
||
<div className="flex gap-2 mb-6">
|
||
<button
|
||
onClick={() => setActiveTab('form')}
|
||
className={`px-6 py-3 rounded-lg font-medium transition ${
|
||
activeTab === 'form'
|
||
? 'bg-primary-600 text-white'
|
||
: 'bg-white text-gray-700 hover:bg-gray-100'
|
||
}`}
|
||
>
|
||
{language === 'ko' ? '새 문의' : 'New Inquiry'}
|
||
</button>
|
||
<button
|
||
onClick={() => setActiveTab('history')}
|
||
className={`px-6 py-3 rounded-lg font-medium transition ${
|
||
activeTab === 'history'
|
||
? 'bg-primary-600 text-white'
|
||
: 'bg-white text-gray-700 hover:bg-gray-100'
|
||
}`}
|
||
>
|
||
{language === 'ko' ? '내 문의 내역' : 'My Inquiries'} ({myInquiries.length})
|
||
</button>
|
||
</div>
|
||
)}
|
||
|
||
{/* Inquiry History Tab */}
|
||
{user && activeTab === 'history' && (
|
||
<div className="bg-white rounded-2xl shadow-lg p-6">
|
||
<h2 className="text-xl font-bold text-gray-800 mb-6">
|
||
{language === 'ko' ? '내 문의 내역' : 'My Inquiries'}
|
||
</h2>
|
||
|
||
{loadingInquiries ? (
|
||
<div className="p-8 text-center">
|
||
<div className="animate-spin w-8 h-8 border-4 border-primary-600 border-t-transparent rounded-full mx-auto"></div>
|
||
</div>
|
||
) : myInquiries.length === 0 ? (
|
||
<div className="p-12 text-center text-gray-500">
|
||
{language === 'ko' ? '문의 내역이 없습니다.' : 'No inquiries yet.'}
|
||
</div>
|
||
) : (
|
||
<div className="space-y-4">
|
||
{myInquiries.map((inquiry) => (
|
||
<div
|
||
key={inquiry.id}
|
||
onClick={() => openInquiryDetail(inquiry)}
|
||
className="border rounded-lg p-4 hover:bg-gray-50 cursor-pointer transition"
|
||
>
|
||
<div className="flex items-center justify-between mb-2">
|
||
<div className="flex items-center gap-2">
|
||
<span className="text-sm bg-gray-100 px-2 py-0.5 rounded">
|
||
{categoryLabels[inquiry.category] || inquiry.category}
|
||
</span>
|
||
<span className={`text-xs px-2 py-0.5 rounded-full ${STATUS_COLORS[inquiry.status]}`}>
|
||
{statusLabels[inquiry.status] || inquiry.status}
|
||
</span>
|
||
</div>
|
||
<span className="text-xs text-gray-500">{formatDate(inquiry.created_at)}</span>
|
||
</div>
|
||
<h3 className="font-medium text-gray-800">{inquiry.subject || (language === 'ko' ? '제목 없음' : 'No subject')}</h3>
|
||
<p className="text-sm text-gray-500 truncate">{inquiry.message}</p>
|
||
{inquiry.admin_response && (
|
||
<p className="text-xs text-green-600 mt-2">
|
||
{language === 'ko' ? '답변 완료' : 'Answered'}
|
||
</p>
|
||
)}
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
|
||
{/* Form Tab */}
|
||
{(!user || activeTab === 'form') && (
|
||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
|
||
{/* Left Column - Company Info */}
|
||
<div className="space-y-8">
|
||
<div className="bg-white rounded-2xl shadow-lg p-8">
|
||
<h2 className="text-2xl font-bold text-gray-800 mb-6 flex items-center gap-3">
|
||
<span className="w-10 h-10 bg-primary-100 text-primary-600 rounded-full flex items-center justify-center">
|
||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||
</svg>
|
||
</span>
|
||
{t.getInTouch}
|
||
</h2>
|
||
|
||
<div className="space-y-5">
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||
<svg className="w-6 h-6 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<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" />
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<p className="text-sm text-gray-500 mb-1">{language === 'ko' ? '주소' : 'Address'}</p>
|
||
<p className="font-semibold text-gray-800">{t.companyAddress}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||
<svg className="w-6 h-6 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<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" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<p className="text-sm text-gray-500 mb-1">{t.telephone}</p>
|
||
<p className="font-semibold text-gray-800">+82-2-552-0773</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||
<svg className="w-6 h-6 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.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" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<p className="text-sm text-gray-500 mb-1">{t.emailAddress}</p>
|
||
<a href="mailto:sshong@grantech.kr" className="font-semibold text-primary-600 hover:text-primary-700">
|
||
sshong@grantech.kr
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center flex-shrink-0">
|
||
<svg className="w-6 h-6 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<p className="text-sm text-gray-500 mb-1">{t.businessHours}</p>
|
||
<p className="font-semibold text-gray-800">{t.businessHoursValue}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Map */}
|
||
<div className="bg-white rounded-2xl shadow-lg overflow-hidden">
|
||
<div className="h-64">
|
||
<iframe
|
||
src="https://maps.google.com/maps?q=경기도+안산시+단원구+별망로+453+광양프런티어밸리&t=&z=16&ie=UTF8&iwloc=&output=embed"
|
||
width="100%"
|
||
height="100%"
|
||
style={{ border: 0 }}
|
||
allowFullScreen
|
||
loading="lazy"
|
||
title="Location"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Right Column - Form */}
|
||
<div className="bg-white rounded-2xl shadow-lg p-8">
|
||
<h2 className="text-2xl font-bold text-gray-800 mb-6 flex items-center gap-3">
|
||
<span className="w-10 h-10 bg-primary-100 text-primary-600 rounded-full flex items-center justify-center">
|
||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
|
||
</svg>
|
||
</span>
|
||
{t.sendUsMessage}
|
||
</h2>
|
||
|
||
{isSubmitted ? (
|
||
<div className="text-center py-12">
|
||
<div className="w-20 h-20 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-6">
|
||
<svg className="w-10 h-10 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||
</svg>
|
||
</div>
|
||
<h3 className="text-2xl font-bold text-gray-800 mb-3">{t.messageSent}</h3>
|
||
<p className="text-gray-600 mb-6">{t.messageSentDesc}</p>
|
||
<button
|
||
onClick={() => setIsSubmitted(false)}
|
||
className="text-primary-600 hover:text-primary-700 font-medium"
|
||
>
|
||
{language === 'ko' ? '새 문의 작성' : 'Send another message'}
|
||
</button>
|
||
</div>
|
||
) : (
|
||
<form onSubmit={handleSubmit} className="space-y-6">
|
||
{error && (
|
||
<div className="bg-red-50 text-red-700 p-4 rounded-lg">
|
||
{error}
|
||
</div>
|
||
)}
|
||
|
||
{/* Category */}
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
{language === 'ko' ? '문의 유형' : 'Category'} *
|
||
</label>
|
||
<select
|
||
required
|
||
value={formData.category}
|
||
onChange={(e) => setFormData({ ...formData, category: e.target.value })}
|
||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500"
|
||
>
|
||
{Object.entries(categoryLabels).map(([value, label]) => (
|
||
<option key={value} value={value}>{label}</option>
|
||
))}
|
||
</select>
|
||
</div>
|
||
|
||
{/* Subject */}
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
{language === 'ko' ? '제목' : 'Subject'}
|
||
</label>
|
||
<input
|
||
type="text"
|
||
value={formData.subject}
|
||
onChange={(e) => setFormData({ ...formData, subject: e.target.value })}
|
||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500"
|
||
placeholder={language === 'ko' ? '문의 제목' : 'Subject'}
|
||
/>
|
||
</div>
|
||
|
||
{/* Email & Phone */}
|
||
{!user && (
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">{t.yourEmail} *</label>
|
||
<input
|
||
type="email"
|
||
required
|
||
value={formData.email}
|
||
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500"
|
||
placeholder="example@email.com"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">{t.yourPhone}</label>
|
||
<input
|
||
type="tel"
|
||
value={formData.phone}
|
||
onChange={(e) => setFormData({ ...formData, phone: e.target.value })}
|
||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500"
|
||
placeholder="+82-10-1234-5678"
|
||
/>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Message */}
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">{t.message} *</label>
|
||
<textarea
|
||
required
|
||
rows={6}
|
||
value={formData.message}
|
||
onChange={(e) => setFormData({ ...formData, message: e.target.value })}
|
||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 resize-none"
|
||
placeholder={language === 'ko' ? '문의 내용을 입력해 주세요...' : 'Enter your message...'}
|
||
/>
|
||
</div>
|
||
|
||
{/* Submit */}
|
||
<button
|
||
type="submit"
|
||
disabled={isSubmitting}
|
||
className="w-full bg-primary-600 text-white font-semibold py-4 rounded-lg hover:bg-primary-700 transition disabled:opacity-50 flex items-center justify-center gap-2"
|
||
>
|
||
{isSubmitting ? (
|
||
<>
|
||
<svg className="animate-spin h-5 w-5" viewBox="0 0 24 24">
|
||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
|
||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
||
</svg>
|
||
<span>{t.submitting}</span>
|
||
</>
|
||
) : (
|
||
<>
|
||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
|
||
</svg>
|
||
<span>{t.send}</span>
|
||
</>
|
||
)}
|
||
</button>
|
||
</form>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* Detail Modal */}
|
||
{showDetailModal && selectedInquiry && (
|
||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
|
||
<div className="bg-white rounded-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto">
|
||
<div className="p-6 border-b sticky top-0 bg-white">
|
||
<div className="flex items-center justify-between">
|
||
<h2 className="text-xl font-bold">{language === 'ko' ? '문의 상세' : 'Inquiry Detail'}</h2>
|
||
<button
|
||
onClick={() => setShowDetailModal(false)}
|
||
className="p-2 hover:bg-gray-100 rounded-full"
|
||
>
|
||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="p-6 space-y-6">
|
||
{/* Info */}
|
||
<div className="flex items-center justify-between">
|
||
<span className="text-sm bg-gray-100 px-2 py-1 rounded">
|
||
{categoryLabels[selectedInquiry.inquiry.category] || selectedInquiry.inquiry.category}
|
||
</span>
|
||
<span className={`text-xs px-2 py-1 rounded-full ${STATUS_COLORS[selectedInquiry.inquiry.status]}`}>
|
||
{statusLabels[selectedInquiry.inquiry.status] || selectedInquiry.inquiry.status}
|
||
</span>
|
||
</div>
|
||
|
||
{/* Original Message */}
|
||
<div className="bg-gray-50 p-4 rounded-lg">
|
||
<p className="font-medium mb-2">{selectedInquiry.inquiry.subject || (language === 'ko' ? '제목 없음' : 'No subject')}</p>
|
||
<p className="text-gray-700 whitespace-pre-wrap">{selectedInquiry.inquiry.message}</p>
|
||
<p className="text-xs text-gray-400 mt-2">{formatDate(selectedInquiry.inquiry.created_at)}</p>
|
||
</div>
|
||
|
||
{/* Messages */}
|
||
{selectedInquiry.messages.length > 0 && (
|
||
<div className="space-y-3">
|
||
<h3 className="font-semibold text-gray-700">{language === 'ko' ? '대화 내역' : 'Messages'}</h3>
|
||
{selectedInquiry.messages.map((msg) => (
|
||
<div
|
||
key={msg.id}
|
||
className={`p-3 rounded-lg ${
|
||
msg.is_admin
|
||
? 'bg-primary-50 border-l-4 border-primary-500'
|
||
: 'bg-gray-50 border-l-4 border-gray-300'
|
||
}`}
|
||
>
|
||
<div className="flex items-center justify-between mb-1">
|
||
<span className={`text-xs font-medium ${msg.is_admin ? 'text-primary-600' : 'text-gray-600'}`}>
|
||
{msg.is_admin ? (language === 'ko' ? '관리자' : 'Admin') : (language === 'ko' ? '나' : 'Me')}
|
||
</span>
|
||
<span className="text-xs text-gray-400">{formatDate(msg.created_at)}</span>
|
||
</div>
|
||
<p className="text-sm text-gray-700 whitespace-pre-wrap">{msg.message}</p>
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
|
||
{/* Reply Form */}
|
||
{selectedInquiry.inquiry.status !== 'closed' && (
|
||
<div>
|
||
<h3 className="font-semibold text-gray-700 mb-2">{language === 'ko' ? '추가 문의' : 'Reply'}</h3>
|
||
<textarea
|
||
value={replyMessage}
|
||
onChange={(e) => setReplyMessage(e.target.value)}
|
||
rows={3}
|
||
className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-primary-500"
|
||
placeholder={language === 'ko' ? '추가 문의 내용을 입력하세요...' : 'Enter your message...'}
|
||
/>
|
||
<button
|
||
onClick={handleSendReply}
|
||
disabled={sendingReply || !replyMessage.trim()}
|
||
className="mt-2 bg-primary-600 text-white px-6 py-2 rounded-lg hover:bg-primary-700 disabled:opacity-50"
|
||
>
|
||
{sendingReply ? (language === 'ko' ? '전송중...' : 'Sending...') : (language === 'ko' ? '전송' : 'Send')}
|
||
</button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Business Partnership Section */}
|
||
<section className="bg-gradient-to-r from-primary-800 to-primary-900 py-16">
|
||
<div className="container mx-auto px-4">
|
||
<div className="max-w-4xl mx-auto text-center">
|
||
<div className="flex items-center justify-center gap-3 mb-4">
|
||
<svg className="w-8 h-8 text-yellow-400" fill="currentColor" viewBox="0 0 24 24">
|
||
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" />
|
||
</svg>
|
||
<h2 className="text-2xl md:text-3xl font-bold text-white">
|
||
{language === 'ko' ? '비즈니스 파트너십' :
|
||
language === 'mn' ? 'Бизнесийн түншлэл' :
|
||
language === 'ru' ? 'Деловое партнёрство' :
|
||
'Business Partnership'}
|
||
</h2>
|
||
<svg className="w-8 h-8 text-yellow-400" fill="currentColor" viewBox="0 0 24 24">
|
||
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" />
|
||
</svg>
|
||
</div>
|
||
<p className="text-lg text-primary-100 leading-relaxed mb-8">
|
||
{language === 'ko'
|
||
? '차량 거래뿐만 아니라, 물류, 수출입, 딜러십, 기술 협력 등 다양한 비즈니스 협업 기회를 열린 마음으로 환영합니다. 함께 성장할 파트너를 찾고 있습니다.'
|
||
: language === 'mn'
|
||
? 'Бид зөвхөн автомашины худалдаа төдийгүй логистик, экспорт-импорт, дилер, техникийн хамтын ажиллагаа зэрэг бизнесийн бүх төрлийн санал, хамтын ажиллагааг хүлээн авахад бэлэн байна.'
|
||
: language === 'ru'
|
||
? 'Мы открыты не только для сделок с автомобилями, но и для любых бизнес-предложений: логистика, экспорт-импорт, дилерство, техническое сотрудничество. Мы ищем партнёров для совместного развития.'
|
||
: 'Beyond vehicle transactions, we warmly welcome all business inquiries — logistics, import-export, dealership opportunities, and technical partnerships. We are seeking partners to grow together.'}
|
||
</p>
|
||
<div className="flex flex-wrap justify-center gap-4">
|
||
<div className="bg-white/10 backdrop-blur-sm rounded-lg px-6 py-3 border border-white/20">
|
||
<span className="text-white font-medium">
|
||
{language === 'ko' ? '🚚 물류 협력' : language === 'mn' ? '🚚 Логистик' : language === 'ru' ? '🚚 Логистика' : '🚚 Logistics'}
|
||
</span>
|
||
</div>
|
||
<div className="bg-white/10 backdrop-blur-sm rounded-lg px-6 py-3 border border-white/20">
|
||
<span className="text-white font-medium">
|
||
{language === 'ko' ? '🌍 수출입' : language === 'mn' ? '🌍 Экспорт-Импорт' : language === 'ru' ? '🌍 Экспорт-Импорт' : '🌍 Import-Export'}
|
||
</span>
|
||
</div>
|
||
<div className="bg-white/10 backdrop-blur-sm rounded-lg px-6 py-3 border border-white/20">
|
||
<span className="text-white font-medium">
|
||
{language === 'ko' ? '🤝 딜러십' : language === 'mn' ? '🤝 Дилерийн эрх' : language === 'ru' ? '🤝 Дилерство' : '🤝 Dealership'}
|
||
</span>
|
||
</div>
|
||
<div className="bg-white/10 backdrop-blur-sm rounded-lg px-6 py-3 border border-white/20">
|
||
<span className="text-white font-medium">
|
||
{language === 'ko' ? '💡 기술 협력' : language === 'mn' ? '💡 Техникийн хамтын ажиллагаа' : language === 'ru' ? '💡 Техническое сотрудничество' : '💡 Tech Partnership'}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
);
|
||
}
|