demo talep formu

This commit is contained in:
Sedat Öztürk 2025-06-22 23:49:49 +03:00
parent f01bcd440c
commit 6d1516eb0f
8 changed files with 505 additions and 265 deletions

View file

@ -4,19 +4,19 @@ using System.Threading.Tasks;
using Kurs.Platform.Data.Seeds; using Kurs.Platform.Data.Seeds;
using Kurs.Sender.Mail; using Kurs.Sender.Mail;
using Volo.Abp.Settings; using Volo.Abp.Settings;
using Volo.Abp.UI.Navigation.Urls;
namespace Kurs.Platform.Dashboard; namespace Kurs.Platform.Dashboard;
public class ContactFormDto public class ContactFormDto
{ {
public string Company { get; set; } public string OrganizationName { get; set; }
public string FullName { get; set; } public string FullName { get; set; }
public string Email { get; set; } public string Email { get; set; }
public string Phone { get; set; } public string Phone { get; set; }
public string Address { get; set; } public string Address { get; set; }
public string BranchCount { get; set; } public string NumberOfBranches { get; set; }
public string UserCount { get; set; } public string NumberOfUsers { get; set; }
public string Message { get; set; } public string Message { get; set; }
} }
@ -37,13 +37,13 @@ public class DemoAppService : PlatformAppService
public async Task DemoFormAsync(ContactFormDto input) public async Task DemoFormAsync(ContactFormDto input)
{ {
var bodyBuilder = new StringBuilder(); var bodyBuilder = new StringBuilder();
bodyBuilder.AppendLine($"Şirket: {input.Company}"); bodyBuilder.AppendLine($"Şirket: {input.OrganizationName}");
bodyBuilder.AppendLine($"Ad Soyad: {input.FullName}"); bodyBuilder.AppendLine($"Ad Soyad: {input.FullName}");
bodyBuilder.AppendLine($"E-Posta: {input.Email}"); bodyBuilder.AppendLine($"E-Posta: {input.Email}");
bodyBuilder.AppendLine($"Telefon: {input.Phone}"); bodyBuilder.AppendLine($"Telefon: {input.Phone}");
bodyBuilder.AppendLine($"Adres: {input.Address}"); bodyBuilder.AppendLine($"Adres: {input.Address}");
bodyBuilder.AppendLine($"Şube Sayısı: {input.BranchCount}"); bodyBuilder.AppendLine($"Şube Sayısı: {input.NumberOfBranches}");
bodyBuilder.AppendLine($"Kullanıcı Sayısı: {input.UserCount}"); bodyBuilder.AppendLine($"Kullanıcı Sayısı: {input.NumberOfUsers}");
bodyBuilder.AppendLine($"Mesaj: {input.Message}"); bodyBuilder.AppendLine($"Mesaj: {input.Message}");
var SenderName = await settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromDisplayName); var SenderName = await settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromDisplayName);

View file

@ -11,6 +11,8 @@ import Contact from './pages/Contact';
import BlogDetail from './pages/BlogDetail'; import BlogDetail from './pages/BlogDetail';
import NotFound from './pages/NotFound'; import NotFound from './pages/NotFound';
import { LanguageProvider } from './context/LanguageContext'; import { LanguageProvider } from './context/LanguageContext';
import { useState } from 'react';
import Demo from './pages/Demo';
// Create a client // Create a client
const queryClient = new QueryClient({ const queryClient = new QueryClient({
@ -23,11 +25,16 @@ const queryClient = new QueryClient({
}); });
function App() { function App() {
const [isDemoModalOpen, setIsDemoModalOpen] = useState(false);
const openDemoModal = () => setIsDemoModalOpen(true);
const closeDemoModal = () => setIsDemoModalOpen(false);
return ( return (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<LanguageProvider> <LanguageProvider>
<Router> <Router>
<Layout> <Layout openDemoModal={openDemoModal}>
<Routes> <Routes>
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
<Route path="/about" element={<About />} /> <Route path="/about" element={<About />} />
@ -39,6 +46,7 @@ function App() {
<Route path="*" element={<NotFound />} /> <Route path="*" element={<NotFound />} />
</Routes> </Routes>
</Layout> </Layout>
<Demo isOpen={isDemoModalOpen} onClose={closeDemoModal} />
<Toaster position="top-right" /> <Toaster position="top-right" />
</Router> </Router>
</LanguageProvider> </LanguageProvider>

View file

@ -14,7 +14,11 @@ import Logo from "./Logo";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useLanguage } from "../../context/LanguageContext"; import { useLanguage } from "../../context/LanguageContext";
const Header: React.FC = () => { interface HeaderProps {
openDemoModal: () => void;
}
const Header: React.FC<HeaderProps> = ({ openDemoModal }) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [scrolled, setScrolled] = useState(false); const [scrolled, setScrolled] = useState(false);
const { language, setLanguage, t } = useLanguage(); const { language, setLanguage, t } = useLanguage();
@ -41,8 +45,9 @@ const Header: React.FC = () => {
{ name: t("nav.products"), path: "/products", icon: Package }, { name: t("nav.products"), path: "/products", icon: Package },
{ name: t("nav.services"), path: "/services", icon: Briefcase }, { name: t("nav.services"), path: "/services", icon: Briefcase },
{ name: t("nav.blog"), path: "/blog", icon: BookOpen }, { name: t("nav.blog"), path: "/blog", icon: BookOpen },
{ name: t("nav.demo"), action: openDemoModal, icon: Globe },
{ name: t("nav.contact"), path: "/contact", icon: Phone }, { name: t("nav.contact"), path: "/contact", icon: Phone },
{ name: t("nav.demo"), path: import.meta.env.VITE_KURS_URL }, { name: t("nav.giris"), path: import.meta.env.VITE_KURS_URL },
]; ];
return ( return (
@ -60,17 +65,29 @@ const Header: React.FC = () => {
{/* Desktop Navigation */} {/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-6"> <nav className="hidden md:flex items-center space-x-6">
{navLinks.map((link) => ( {navLinks.map((link) =>
<Link link.path ? (
key={link.path} <Link
to={link.path} key={link.path}
className={`font-medium text-sm text-white hover:text-blue-400 transition-colors ${ to={link.path}
link.name === "Giriş" || link.name === "Login" ? "bg-blue-600 rounded px-2 py-1" : "" className={`font-medium text-sm text-white hover:text-blue-400 transition-colors ${
}`} link.name === "Giriş" || link.name === "Login" ? "bg-blue-600 rounded px-2 py-1" : ""
> }`}
{link.name} >
</Link> {link.name}
))} </Link>
) : (
<button
key={link.name}
onClick={link.action}
className={`font-medium text-sm text-white hover:text-blue-400 transition-colors ${
link.name === "Giriş" || link.name === "Login" ? "bg-blue-600 rounded px-2 py-1" : ""
}`}
>
{link.name}
</button>
)
)}
<button <button
onClick={toggleLanguage} onClick={toggleLanguage}
@ -96,18 +113,33 @@ const Header: React.FC = () => {
<div className="md:hidden bg-gray-900/95 backdrop-blur-sm shadow-lg"> <div className="md:hidden bg-gray-900/95 backdrop-blur-sm shadow-lg">
<div className="container mx-auto px-4 py-2"> <div className="container mx-auto px-4 py-2">
<nav className="flex flex-col space-y-4 py-4"> <nav className="flex flex-col space-y-4 py-4">
{navLinks.map((link) => ( {navLinks.map((link) =>
<Link link.path ? (
key={link.path} <Link
to={link.path} key={link.path}
className={`font-medium text-white hover:text-blue-400 transition-colors ${ to={link.path}
link.name === "Giriş" || link.name === "Login" ? "bg-blue-600 rounded px-2 py-1" : "" className={`font-medium text-white hover:text-blue-400 transition-colors ${
}`} link.name === "Giriş" || link.name === "Login" ? "bg-blue-600 rounded px-2 py-1" : ""
onClick={toggleMenu} }`}
> onClick={toggleMenu}
{link.name} >
</Link> {link.name}
))} </Link>
) : (
<button
key={link.name}
onClick={() => {
link.action && link.action();
toggleMenu();
}}
className={`font-medium text-white hover:text-blue-400 transition-colors ${
link.name === "Giriş" || link.name === "Login" ? "bg-blue-600 rounded px-2 py-1" : ""
}`}
>
{link.name}
</button>
)
)}
<button <button
onClick={toggleLanguage} onClick={toggleLanguage}

View file

@ -5,9 +5,10 @@ import Footer from './Footer';
interface LayoutProps { interface LayoutProps {
children: React.ReactNode; children: React.ReactNode;
openDemoModal: () => void;
} }
const Layout: React.FC<LayoutProps> = ({ children }) => { const Layout: React.FC<LayoutProps> = ({ children, openDemoModal }) => {
const location = useLocation(); const location = useLocation();
useEffect(() => { useEffect(() => {
@ -16,7 +17,7 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
return ( return (
<div className="flex flex-col min-h-screen"> <div className="flex flex-col min-h-screen">
<Header /> <Header openDemoModal={openDemoModal} />
<main className="flex-grow"> <main className="flex-grow">
{children} {children}
</main> </main>
@ -25,4 +26,4 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
); );
}; };
export default Layout; export default Layout;

View file

@ -15,7 +15,8 @@ const translations = {
"nav.about": "Hakkımızda", "nav.about": "Hakkımızda",
"nav.products": "Ürünler", "nav.products": "Ürünler",
"nav.services": "Hizmetler", "nav.services": "Hizmetler",
"nav.demo": "Giriş", "nav.demo": "Demo",
"nav.giris": "Giriş",
"nav.blog": "Blog", "nav.blog": "Blog",
"nav.forum": "Forum", "nav.forum": "Forum",
"nav.contact": "İletişim", "nav.contact": "İletişim",
@ -123,9 +124,17 @@ const translations = {
"services.cta.description": "services.cta.description":
"İşletmenizin ihtiyaçlarına özel çözümlerimizle rekabette öne geçin. Danışmanlık için bize ulaşın.", "İşletmenizin ihtiyaçlarına özel çözümlerimizle rekabette öne geçin. Danışmanlık için bize ulaşın.",
"services.cta.contact": "İletişime Geçin", "services.cta.contact": "İletişime Geçin",
"demo.form.title": "Demo Talep Formu", "demo.title": "Demo Talep Formu",
"demo.subtitle": "demo.subtitle": "Sorularınız için bizimle iletişime geçin. Size yardımcı olmaktan mutluluk duyarız.",
"Sorularınız için bizimle iletişime geçin. Size yardımcı olmaktan mutluluk duyarız.", "demo.send": "Demo Talebi Gönder",
"demo.organizationName": "Organizasyon adınızı girin",
"demo.fullName": "Ad soyadınızı girin",
"demo.email": "ornek@email.com",
"demo.phone": "+90 (555) 123-4567",
"demo.address": "Adresinizi girin",
"demo.branches": "örn. 5",
"demo.users": "örn. 50",
"demo.message": "İhtiyaçlarınız ve demoda görmek istediğiniz özellikler hakkında bize bilgi verin...",
// Services Page // Services Page
"services.title": "Hizmetlerimiz", "services.title": "Hizmetlerimiz",
@ -421,7 +430,8 @@ const translations = {
"nav.about": "About Us", "nav.about": "About Us",
"nav.products": "Products", "nav.products": "Products",
"nav.services": "Services", "nav.services": "Services",
"nav.demo": "Login", "nav.demo": "Demo",
"nav.giris": "Login",
"nav.blog": "Blog", "nav.blog": "Blog",
"nav.forum": "Forum", "nav.forum": "Forum",
"nav.contact": "Contact", "nav.contact": "Contact",
@ -533,9 +543,17 @@ const translations = {
"services.cta.description": "services.cta.description":
"Gain a competitive edge with our tailored solutions. Contact us for a consultation.", "Gain a competitive edge with our tailored solutions. Contact us for a consultation.",
"services.cta.contact": "Get in Touch", "services.cta.contact": "Get in Touch",
"demo.form.title": "Demo Request Form", "demo.title": "Demo Request Form",
"demo.subtitle": "demo.subtitle":"Contact us for any inquiries. We are happy to assist you.",
"Contact us for any inquiries. We are happy to assist you.", "demo.send": "Send Demo Request",
"demo.organizationName": "Enter your organization name",
"demo.fullName": "Enter your name and surname",
"demo.email": "sample@email.com",
"demo.phone": "+90 (555) 123-4567",
"demo.address": "Enter your address",
"demo.branches": "sample 5",
"demo.users": "sample 50",
"demo.message": "Tell us about your needs and the features you would like to see in the demo...",
// Services Page // Services Page
"services.title": "Our Services", "services.title": "Our Services",

View file

@ -1,4 +1,4 @@
import React, { useState } from "react"; import React from "react";
import { import {
Mail, Mail,
Phone, Phone,
@ -10,55 +10,10 @@ import {
MessageCircle, MessageCircle,
} from "lucide-react"; } from "lucide-react";
import { useLanguage } from "../context/LanguageContext"; import { useLanguage } from "../context/LanguageContext";
import { demoService } from "../services/api/demo.service";
const Contact: React.FC = () => { const Contact: React.FC = () => {
const { t } = useLanguage(); const { t } = useLanguage();
const [formData, setFormData] = useState({
company: "",
fullName: "",
email: "",
phone: "",
address: "",
branchCount: "",
userCount: "",
message: "",
});
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
const { name, value } = e.target;
setFormData((prev: any) => ({
...prev,
[name]: value,
}));
};
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
await demoService.createDemoForm(formData);
alert("Form başarıyla gönderildi.");
setFormData({
company: "",
fullName: "",
email: "",
phone: "",
address: "",
branchCount: "",
userCount: "",
message: "",
});
} catch (error) {
console.error("Gönderim hatası:", error);
alert("Sunucuya ulaşılamıyor.");
}
};
return ( return (
<div className="min-h-screen bg-gray-50"> <div className="min-h-screen bg-gray-50">
{/* Hero Section */} {/* Hero Section */}
@ -187,183 +142,26 @@ const Contact: React.FC = () => {
</div> </div>
</div> </div>
<div className="space-y-8"> {/* Map Section */}
<div className="bg-white rounded-xl shadow-lg p-8"> <div className="bg-white rounded-xl shadow-lg p-8">
<h2 className="text-2xl font-bold text-gray-900 mb-6"> <h2 className="text-2xl font-bold text-gray-900 mb-8 text-center">
{t("demo.form.title")} {t("contact.location")}
</h2> </h2>
<form className="space-y-6" onSubmit={handleSubmit}> <div className="aspect-w-16 aspect-h-9 bg-gray-200 rounded-xl overflow-hidden">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <iframe
<div> src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3006.209566407676!2d28.757000999999992!3d41.10811400000001!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x8a0bbbdfcfd3fd24!2zU8O2enNvZnQ!5e0!3m2!1str!2str!4v1450816303558"
<label width="100%"
htmlFor="company" height="740"
className="block text-sm font-medium text-gray-700 mb-2" style={{ border: 0 }}
> allowFullScreen
{t("common.company")} loading="lazy"
</label> referrerPolicy="no-referrer-when-downgrade"
<input ></iframe>
type="text"
id="company"
name="company"
value={formData.company}
onChange={handleChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label
htmlFor="fullName"
className="block text-sm font-medium text-gray-700 mb-2"
>
{t("common.fullName") || "Adınız Soyadınız"}
</label>
<input
type="text"
id="fullName"
name="fullName"
value={formData.fullName}
onChange={handleChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-gray-700 mb-2"
>
{t("common.email")}
</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label
htmlFor="phone"
className="block text-sm font-medium text-gray-700 mb-2"
>
{t("common.phone")}
</label>
<input
type="tel"
id="phone"
name="phone"
value={formData.phone}
onChange={handleChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
</div>
<div>
<label
htmlFor="address"
className="block text-sm font-medium text-gray-700 mb-2"
>
{t("common.address")}
</label>
<input
type="text"
id="address"
name="address"
value={formData.address}
onChange={handleChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label
htmlFor="branchCount"
className="block text-sm font-medium text-gray-700 mb-2"
>
{t("common.branchCount") || "Şube Adedi"}
</label>
<input
type="number"
id="branchCount"
name="branchCount"
value={formData.branchCount}
onChange={handleChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label
htmlFor="userCount"
className="block text-sm font-medium text-gray-700 mb-2"
>
{t("common.userCount") || "Kullanıcı Adedi"}
</label>
<input
type="number"
id="userCount"
name="userCount"
value={formData.userCount}
onChange={handleChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
</div>
<div>
<label
htmlFor="message"
className="block text-sm font-medium text-gray-700 mb-2"
>
{t("common.message")}
</label>
<textarea
id="message"
name="message"
rows={10}
value={formData.message}
onChange={handleChange}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<button
type="submit"
className="w-full bg-blue-600 text-white py-3 px-6 rounded-lg hover:bg-blue-700 transition-colors font-semibold"
>
{t("common.send")}
</button>
</form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{/* Map Section */}
<div className="bg-white py-16">
<div className="container mx-auto px-4">
<h2 className="text-2xl font-bold text-gray-900 mb-8 text-center">
{t("contact.location")}
</h2>
<div className="aspect-w-16 aspect-h-9 bg-gray-200 rounded-xl overflow-hidden">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3006.209566407676!2d28.757000999999992!3d41.10811400000001!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x8a0bbbdfcfd3fd24!2zU8O2enNvZnQ!5e0!3m2!1str!2str!4v1450816303558"
width="100%"
height="450"
style={{ border: 0 }}
allowFullScreen
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
></iframe>
</div>
</div>
</div>
</div> </div>
); );
}; };

383
company/src/pages/Demo.tsx Normal file
View file

@ -0,0 +1,383 @@
import React, { useEffect, useState } from "react";
import { useLanguage } from "../context/LanguageContext";
import { demoService } from "../services/api/demo.service";
import {
Building2,
User,
Mail,
Phone,
MapPin,
Users,
MessageSquare,
Send,
CheckCircle,
} from "lucide-react";
interface DemoModalProps {
isOpen: boolean;
onClose: () => void;
}
interface FormData {
organizationName: string;
fullName: string;
email: string;
phone: string;
address: string;
numberOfBranches: string;
numberOfUsers: string;
message: string;
}
const Demo: React.FC<DemoModalProps> = ({ isOpen, onClose }) => {
const { t } = useLanguage();
const [formData, setFormData] = useState<FormData>({
organizationName: "",
fullName: "",
email: "",
phone: "",
address: "",
numberOfBranches: "",
numberOfUsers: "",
message: "",
});
const [errors, setErrors] = useState<Partial<FormData>>({});
const [isSubmitted, setIsSubmitted] = useState(false);
const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
if (errors[name as keyof FormData]) {
setErrors((prev) => ({
...prev,
[name]: "",
}));
}
};
const validateForm = (): boolean => {
const newErrors: Partial<FormData> = {};
if (!formData.organizationName.trim())
newErrors.organizationName = "Organization name is required";
if (!formData.fullName.trim()) newErrors.fullName = "Full name is required";
if (!formData.email.trim()) {
newErrors.email = "Email is required";
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
newErrors.email = "Please enter a valid email";
}
if (!formData.phone.trim()) newErrors.phone = "Phone number is required";
if (!formData.address.trim()) newErrors.address = "Address is required";
if (!formData.numberOfBranches.trim())
newErrors.numberOfBranches = "Number of branches is required";
if (!formData.numberOfUsers.trim())
newErrors.numberOfUsers = "Number of users is required";
if (!formData.message.trim()) newErrors.message = "Message is required";
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!validateForm()) return;
try {
await demoService.createDemoForm(formData);
setIsSubmitted(true);
onClose(); // modal'ı otomatik kapat
} catch (error) {
console.error("Gönderim hatası:", error);
alert("Sunucuya ulaşılamıyor.");
}
};
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === "Escape") {
onClose();
}
};
if (isOpen) {
window.addEventListener("keydown", handleKeyDown);
}
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [isOpen, onClose]);
// 🎉 Gönderim sonrası teşekkür ekranı
if (isSubmitted) {
return (
<div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto py-5 z-50">
<div className="mx-auto bg-white rounded-xl shadow-lg max-w-md w-full relative">
<div className="max-w-md w-full bg-gradient-to-br from-blue-50 to-indigo-100 rounded-3xl p-8 text-center border border-blue-200 shadow-xl">
{/* Kapat Butonu */}
<button
onClick={() => setIsSubmitted(false)}
className="absolute top-4 right-4 text-gray-500 hover:text-gray-800 text-2xl"
>
&times;
</button>
<div className="w-16 h-16 bg-green-500 rounded-full flex items-center justify-center mx-auto mb-6">
<CheckCircle className="w-8 h-8 text-white" />
</div>
<h2 className="text-2xl font-bold text-gray-800 mb-4">
Teşekkürler!
</h2>
<p className="text-gray-600 mb-6">
Demo talebiniz başarıyla gönderildi. 24 saat içinde size geri
dönüş yapacağız.
</p>
<button
onClick={() => {
setIsSubmitted(false);
setFormData({
organizationName: "",
fullName: "",
email: "",
phone: "",
address: "",
numberOfBranches: "",
numberOfUsers: "",
message: "",
});
}}
className="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-xl transition-all duration-300"
>
Yeni Talep Gönder
</button>
</div>
</div>
</div>
);
}
// Modal kapalıysa render etme
if (!isOpen) return null;
// 🎯 Normal form ekranı
return (
<div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto py-5 z-50">
<div className="mx-auto bg-white rounded-xl shadow-lg max-w-2xl w-full relative">
<button
onClick={onClose}
className="absolute top-4 right-4 text-gray-500 hover:text-gray-800 text-2xl"
>
&times;
</button>
<form
onSubmit={handleSubmit}
className="bg-white rounded-3xl p-6 lg:p-8 shadow-xl border border-gray-100"
>
<div className="space-y-3">
{/* Organization Name */}
<div>
<label className="block text-gray-700 text-sm font-medium mb-2">
{t('common.company')} *
</label>
<div className="relative">
<Building2 className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="text"
autoFocus
name="organizationName"
value={formData.organizationName}
onChange={handleInputChange}
className={`w-full pl-11 pr-4 py-2.5 bg-gray-50 border ${
errors.organizationName
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-200 focus:border-blue-500 focus:ring-blue-500/20"
} rounded-xl text-gray-800 placeholder-gray-500 focus:outline-none transition-all duration-300`}
placeholder={t('demo.organizationName')}
/>
</div>
</div>
{/* Full Name */}
<div>
<label className="block text-gray-700 text-sm font-medium mb-2">
{t('common.fullName')} *
</label>
<div className="relative">
<User className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="text"
name="fullName"
value={formData.fullName}
onChange={handleInputChange}
className={`w-full pl-11 pr-4 py-2.5 bg-gray-50 border ${
errors.fullName
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-200 focus:border-blue-500 focus:ring-blue-500/20"
} rounded-xl text-gray-800 placeholder-gray-500 focus:outline-none transition-all duration-300`}
placeholder={t('demo.fullName')}
/>
</div>
</div>
{/* Email & Phone Row */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-gray-700 text-sm font-medium mb-2">
{t('common.email')} *
</label>
<div className="relative">
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="email"
name="email"
value={formData.email}
onChange={handleInputChange}
className={`w-full pl-11 pr-4 py-2.5 bg-gray-50 border ${
errors.email
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-200 focus:border-blue-500 focus:ring-blue-500/20"
} rounded-xl text-gray-800 placeholder-gray-500 focus:outline-none transition-all duration-300`}
placeholder={t('demo.email')}
/>
</div>
</div>
<div>
<label className="block text-gray-700 text-sm font-medium mb-2">
{t('common.phone')} *
</label>
<div className="relative">
<Phone className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleInputChange}
className={`w-full pl-11 pr-4 py-2.5 bg-gray-50 border ${
errors.phone
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-200 focus:border-blue-500 focus:ring-blue-500/20"
} rounded-xl text-gray-800 placeholder-gray-500 focus:outline-none transition-all duration-300`}
placeholder={t('demo.phone')}
/>
</div>
</div>
</div>
{/* Address */}
<div>
<label className="block text-gray-700 text-sm font-medium mb-2">
{t('common.address')} *
</label>
<div className="relative">
<MapPin className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="text"
name="address"
value={formData.address}
onChange={handleInputChange}
className={`w-full pl-11 pr-4 py-2.5 bg-gray-50 border ${
errors.address
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-200 focus:border-blue-500 focus:ring-blue-500/20"
} rounded-xl text-gray-800 placeholder-gray-500 focus:outline-none transition-all duration-300`}
placeholder={t('demo.address')}
/>
</div>
</div>
{/* Branches & Users Row */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-gray-700 text-sm font-medium mb-2">
{t('common.branchCount')} *
</label>
<div className="relative">
<Building2 className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="number"
name="numberOfBranches"
value={formData.numberOfBranches}
onChange={handleInputChange}
className={`w-full pl-11 pr-4 py-2.5 bg-gray-50 border ${
errors.numberOfBranches
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-200 focus:border-blue-500 focus:ring-blue-500/20"
} rounded-xl text-gray-800 placeholder-gray-500 focus:outline-none transition-all duration-300`}
placeholder={t('demo.branches')}
min="1"
/>
</div>
</div>
<div>
<label className="block text-gray-700 text-sm font-medium mb-2">
{t('common.userCount')} *
</label>
<div className="relative">
<Users className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="number"
name="numberOfUsers"
value={formData.numberOfUsers}
onChange={handleInputChange}
className={`w-full pl-11 pr-4 py-2.5 bg-gray-50 border ${
errors.numberOfUsers
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-200 focus:border-blue-500 focus:ring-blue-500/20"
} rounded-xl text-gray-800 placeholder-gray-500 focus:outline-none transition-all duration-300`}
placeholder={t('demo.users')}
min="1"
/>
</div>
</div>
</div>
{/* Message */}
<div>
<label className="block text-gray-700 text-sm font-medium mb-2">
{t('common.message')} *
</label>
<div className="relative">
<MessageSquare className="absolute left-3 top-3 w-5 h-5 text-gray-400" />
<textarea
name="message"
value={formData.message}
onChange={handleInputChange}
rows={4}
className={`w-full pl-11 pr-4 py-2.5 bg-gray-50 border ${
errors.message
? "border-red-500 focus:border-red-500 focus:ring-red-500/20"
: "border-gray-200 focus:border-blue-500 focus:ring-blue-500/20"
} rounded-xl text-gray-800 placeholder-gray-500 focus:outline-none transition-all duration-300 resize-none`}
placeholder={t('demo.message')}
/>
</div>
</div>
{/* Submit Button */}
<button
type="submit"
className="w-full bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white font-semibold py-4 px-6 rounded-xl transition-all duration-300 transform hover:scale-[1.02] hover:shadow-lg flex items-center justify-center gap-2"
>
<Send className="w-5 h-5" />
{t('demo.send')}
</button>
</div>
</form>
</div>
</div>
);
};
export default Demo;

View file

@ -1,13 +1,13 @@
import { apiClient } from './config' import { apiClient } from './config'
export interface DemoFormRequest { export interface DemoFormRequest {
company: string organizationName: string
fullName: string fullName: string
email: string email: string
phone: string phone: string
address: string address: string
branchCount: string numberOfBranches: string
userCount: string numberOfUsers: string
message: string message: string
} }