submit form contactus and start api projects

This commit is contained in:
zahravaziri
2025-06-09 17:14:44 +03:30
parent 11446b98e4
commit 3e9143f32c
18 changed files with 515 additions and 35 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ export default async function Contact({ params }: { params: IPageParams }) {
/>
<div className="relative flex w-full flex-col bg-gray-200 pt-4 md:pt-28">
<div className="absolute inset-x-0 inset-y-64 z-10 flex items-end justify-start">
<div className="absolute inset-x-0 inset-y-64 z-2 flex items-end justify-start">
<div className="max-md:hidden md:w-1/2">
<Image
alt="footer-bg"
+2
View File
@@ -2,6 +2,7 @@ import Header from '@/components/layout/header';
import AboutTopInfo from '@/components/pages/about/TopInfo';
import HomeStorySection from '@/components/pages/home/HomeStorySection';
import HomePageProducts from '@/components/pages/home/Products';
import HomePageProjects from '@/components/pages/home/Projects';
import type { IPageParams } from '@/models/layout.d';
import { getTranslations } from 'next-intl/server';
@@ -15,6 +16,7 @@ export default async function Home({ params }: { params: IPageParams }) {
<Header />
<AboutTopInfo />
<HomePageProducts locale={locale} />
<HomePageProjects locale={locale} />
<HomeStorySection className="my-24" />
</main>
);
@@ -7,6 +7,7 @@ const filePath = path.resolve(process.cwd(), 'contactMessages.json');
export async function POST(request: NextRequest) {
try {
const body = await request.json();
console.log(body)
const { first_name, last_name, phone, email, message } = body;
if (!first_name || !last_name || !phone || !email || !message) {
@@ -25,7 +26,9 @@ export async function POST(request: NextRequest) {
}
const newMessage = {
name,
first_name,
last_name,
phone,
email,
message,
createdAt: new Date().toISOString(),
@@ -41,6 +44,8 @@ export async function POST(request: NextRequest) {
message: 'Your message has been received.',
});
} catch (error) {
console.log(error)
console.log(error)
return NextResponse.json(
{ error, message: 'مشکلی پیش آمده.' },
{ status: 400 },
+118
View File
@@ -0,0 +1,118 @@
export const productCategories = [
{
id: '1',
title: 'Ghazaghi',
fa_title: 'قزاقی',
icon: 'categoryGhazaghi',
typesCount: 22,
priceTypeTitle: 'Economy',
fa_priceTypeTitle: 'اقتصادی',
bestForTitle: 'Best For Interior Part',
fa_bestForTitle: 'Best For Interior Part',
fa_description: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`,
description: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`,
},
{
id: '2',
title: 'Ghermez',
fa_title: 'قرمز',
icon: 'categoryGhermez',
typesCount: 12,
priceTypeTitle: 'Luxury',
fa_priceTypeTitle: 'لاکچری',
bestForTitle: 'Best For Exterior Part',
fa_bestForTitle: 'Best For Exterior Part',
fa_description: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`,
description: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`,
},
{
id: '3',
title: 'oryZard',
fa_title: 'زرد',
icon: 'categoryZard',
typesCount: 11,
priceTypeTitle: 'Economy',
fa_priceTypeTitle: 'اقتصادی',
bestForTitle: 'Best For Facing',
fa_bestForTitle: 'Best For Facing',
fa_description: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`,
description: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`,
},
{
id: '40',
title: 'Semirom',
fa_title: 'سمیرم',
icon: 'categorySemirom',
typesCount: 40,
priceTypeTitle: 'Economy',
fa_priceTypeTitle: 'اقتصادی',
bestForTitle: 'Best For Building',
fa_bestForTitle: 'Best For Building',
fa_description: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`,
description: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`,
},
] as APIProductCategoryEntity[];
interface APIProductCategoryEntity {
id: string;
title: string;
fa_title?: string;
icon: string;
typesCount: number;
priceTypeTitle: string;
fa_priceTypeTitle?: string;
bestForTitle: string;
fa_bestForTitle?: string;
fa_description?: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`;
description?: `Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
Facing Bricks: Characteristics and Features`;
}
+51
View File
@@ -0,0 +1,51 @@
import { NextResponse } from 'next/server';
import { cookies } from 'next/headers';
import { productCategories } from './data';
export async function GET(request: Request) {
let data = productCategories;
const cookieStore = await cookies();
const lang = (await cookieStore).get('lang')?.value || 'fa';
if (lang === 'fa') {
data = productCategories.map(
({
id,
title,
fa_title,
icon,
typesCount,
priceTypeTitle,
fa_priceTypeTitle,
bestForTitle,
fa_bestForTitle,
description,
fa_description,
}) => {
if (lang === 'fa') {
return {
id,
icon,
typesCount,
title: fa_title || title,
priceTypeTitle: fa_priceTypeTitle || priceTypeTitle,
bestForTitle: fa_bestForTitle || bestForTitle,
description: fa_description || description,
};
}
return {
id,
icon,
typesCount,
title,
priceTypeTitle,
bestForTitle,
description,
};
},
);
}
return NextResponse.json({ data: productCategories });
}
+125 -9
View File
@@ -1,32 +1,148 @@
'use client';
import { useState } from 'react';
import Button from '@/components/uikit/button';
import FormField from '@/components/uikit/inputs';
import { useTranslations } from 'next-intl';
import api from '@/lib/axios';
import { setContact } from '@/services/contact';
const ContactForm = () => {
const t = useTranslations();
const [formData, setFormData] = useState({
first_name: '',
last_name: '',
email: '',
phone: '',
message: '',
});
const [errors, setErrors] = useState<Record<string, string>>({});
const [loading, setLoading] = useState(false);
const validate = () => {
const newErrors: Record<string, string> = {};
if (!formData.first_name.trim())
newErrors.first_name = t('com_contact_first_name_required');
if (!formData.last_name.trim())
newErrors.last_name = t('com_contact_last_name_required');
if (!formData.email) {
newErrors.email = t('com_contact_email_required');
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
newErrors.email = t('com_contact_email_error');
}
if (!formData.phone) {
newErrors.phone = t('com_contact_phone_required');
} else if (!/^09\d{9}$/.test(formData.phone)) {
newErrors.phone = t('com_contact_phone_error');
}
if (!formData.message.trim()) {
newErrors.message = t('com_contact_textarea_required');
} else if (formData.message.trim().length < 10) {
newErrors.message = t('com_contact_textarea_error');
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleChange = (field: string, value: string) => {
setFormData({ ...formData, [field]: value });
setErrors({ ...errors, [field]: '' });
};
const handleSubmit = (e: React.FormEvent) => {
console.log(e);
e.preventDefault();
setLoading(true);
setContact(formData).finally(() => {
setLoading(false);
});
};
return (
<div className="w-full rounded-4xl bg-white p-4 md:w-1/2">
<form
onSubmit={handleSubmit}
className="z-10 w-full rounded-4xl bg-white p-4 md:w-1/2"
>
<h2 className="mt-8 mb-10 text-5xl text-gray-800">
{t('com_contact_title')}{' '}
<span className="text-5xl font-bold">
{t('com_contact_title_bold')}
</span>
</h2>
<div className="space-y-6">
<div className="flex flex-col gap-6 md:flex-row md:gap-8">
<FormField type="text" placeholder={t('com_contact_first_name')} />
<FormField type="text" placeholder={t('com_contact_last_name')} />
</div>
<FormField type="email" placeholder={t('com_contact_email')} />
<FormField type="tel" placeholder={t('com_contact_phone')} />
<FormField type="textarea" placeholder={t('com_contact_textarea')} />
<div className="w-full">
<FormField
type="text"
placeholder={t('com_contact_first_name')}
value={formData.first_name}
onChange={(e: any) => handleChange('first_name', e.target.value)}
/>
{errors.first_name && (
<p className="text-primary mt-1 text-sm">{errors.first_name}</p>
)}
</div>
<Button>Submit Message</Button>
<div className="w-full">
<FormField
type="text"
placeholder={t('com_contact_last_name')}
value={formData.last_name}
onChange={(e: any) => handleChange('last_name', e.target.value)}
/>
{errors.last_name && (
<p className="text-primary mt-1 text-sm">{errors.last_name}</p>
)}
</div>
</div>
<div>
<FormField
type="email"
placeholder={t('com_contact_email')}
value={formData.email}
onChange={(e: any) => handleChange('email', e.target.value)}
/>
{errors.email && (
<p className="text-primary mt-1 text-sm">{errors.email}</p>
)}
</div>
<div>
<FormField
type="tel"
placeholder={t('com_contact_phone')}
value={formData.phone}
onChange={(e: any) => handleChange('phone', e.target.value)}
/>
{errors.phone && (
<p className="text-primary mt-1 text-sm">{errors.phone}</p>
)}
</div>
<div>
<FormField
type="textarea"
placeholder={t('com_contact_textarea')}
value={formData.message}
onChange={(e: any) => handleChange('message', e.target.value)}
/>
{errors.message && (
<p className="text-primary mt-1 text-sm">{errors.message}</p>
)}
</div>
<Button disabled={loading}>{t('com_contact_button_submit')}</Button>
</div>
</div>
</form>
);
};
+10 -14
View File
@@ -1,5 +1,6 @@
'use client';
import SectionTitle from '@/components/layout/sectionTitle';
import { Icon } from '@/components/uikit/icons';
import { useTranslations } from 'next-intl';
@@ -8,23 +9,18 @@ const TouchUs = () => {
return (
<div className="w-full p-8 md:w-1/2">
<div className="mb-3.5 flex items-center gap-0.5 text-base">
<Icon name="setting" className="text-primary h-4 w-4" />
<p>{t('pages_contact_title')}</p>
</div>
<h1 className="mb-5 text-3xl font-light text-gray-800 md:text-5xl">
{t('com_contact_touch_title')}{' '}
<span className="text-3xl font-light md:text-5xl md:font-bold">
{t('com_contact_touch_title_bold')}
</span>
</h1>
<p className="mb-10 text-base font-normal text-gray-600">
<SectionTitle
title={t('pages_contact_title')}
description={t('com_contact_touch_title')}
description_bold={t('com_contact_touch_title_bold')}
/>
<p className="mt-4 mb-10 text-base font-normal text-gray-600">
{t('com_contact_touch_description')}
</p>
<div className="flex flex-col justify-between gap-10">
<div className="flex items-center">
<div className="mr-4 flex h-10 w-10 items-center justify-center rounded-full bg-red-500">
<div className="me-4 flex h-10 w-10 items-center justify-center rounded-full bg-red-500">
<Icon name="phone" className="text-white" />
</div>
<div>
@@ -36,7 +32,7 @@ const TouchUs = () => {
</div>
<div className="flex items-center">
<div className="mr-4 flex h-10 w-10 items-center justify-center rounded-full bg-red-500">
<div className="me-4 flex h-10 w-10 items-center justify-center rounded-full bg-red-500">
<Icon name="email" className="text-white" />
</div>
<div>
@@ -48,7 +44,7 @@ const TouchUs = () => {
</div>
<div className="flex items-center">
<div className="mr-4 flex h-10 w-10 items-center justify-center rounded-full bg-red-500">
<div className="me-4 flex h-10 w-10 items-center justify-center rounded-full bg-red-500">
<Icon name="location" className="text-white" />
</div>
<div>
+66
View File
@@ -0,0 +1,66 @@
import images from '@/assets/images/images';
import SectionTitle from '@/components/layout/sectionTitle';
import { getProductCategories } from '@/services/products';
import Link from 'next/link';
import routeFactory from '@/assets/constants/routeFactory';
import { getTranslations } from 'next-intl/server';
import { TLocales } from '@/models/layout';
import { getProjectCategories } from '@/services/projects';
import { IProjectCardProps } from '../project/project';
interface Props {
locale: TLocales;
}
export default async function HomePageProjects({ locale }: Props) {
const t = await getTranslations({ locale });
// const projectCategories: IProjectCardProps[] = await getProjectCategories();
const routes = routeFactory(t, locale);
return (
<div className="w-full">
<div
className={`relative w-full bg-white bg-cover bg-fixed bg-center bg-no-repeat pt-28 pb-48`}
// style={{ backgroundImage: `url(${images.homeProductBack.src})` }}
>
<div className="absolute inset-0 z-10 bg-black opacity-50" />
<div className="relative z-20 container mx-auto grid grid-cols-2 gap-28">
<SectionTitle
title={t('pages_product_categories_title')}
description={t('com_home_products_title')}
reverseColor
/>
<h4 className="pt-10 text-base font-extralight tracking-normal text-white">
{t('com_home_products_description')}
</h4>
</div>
</div>
<div className="relative top-[-100px] z-20 container mx-auto w-full">
{/* <div className="grid grid-cols-1 gap-8 rounded-4xl bg-gray-50 py-10 shadow-2xl md:grid-cols-2 lg:grid-cols-4">
{projectCategories.map((category, index) => (
<Link
href={'#'}
key={index}
// href={routes.products.route(index)}
>
<div
className={`flex flex-col items-center justify-center gap-4 p-6 text-center ${index ? 'border-s-[1px] border-gray-100' : ''}`}
>
<h3 className="text-xl font-bold text-gray-500">
{category.title}
</h3>
{/* <p className="text-lg font-light text-gray-400">
{t('com_products_category_types_count', {
count: category.typesCount,
})}
</p>
</div>
</Link>
))}
</div>*/}
</div>
</div>
);
}
+9 -8
View File
@@ -1,39 +1,40 @@
import images from '@/assets/images/images';
import Image from 'next/image';
import Link from 'next/link';
import { IProjectCardProps } from './project';
const projects = [
{
title: 'Sustainable Practices Reducing Waste in Industrial Production',
image: images.projectImg_1.src,
imageSrc: images.projectImg_1.src,
link: '#',
},
{
title: 'Advanced Robotics Revolutionizing Industrial Workflows',
image: images.projectImg_1.src,
imageSrc: images.projectImg_1.src,
link: '#',
},
{
title: 'Top Benefits of the Robotics in Manufacturing',
image: images.projectImg_1.src,
imageSrc: images.projectImg_1.src,
link: '#',
},
{
title: 'Leveraging Data Analytics for Smarter Production',
image: images.projectImg_1.src,
imageSrc: images.projectImg_1.src,
link: '#',
},
{
title: 'Reducing Operational Costs Through Automation',
image: '/images/post5.jpg',
imageSrc: '/images/post5.jpg',
link: '#',
},
{
title: 'The Advantages of Customized Manufacturing Solutions',
image: '/images/post6.jpg',
imageSrc: '/images/post6.jpg',
link: '#',
},
];
] as IProjectCardProps[];
export default function ProjectsGrid() {
return (
@@ -46,7 +47,7 @@ export default function ProjectsGrid() {
>
<div className="relative aspect-[1.09] w-full overflow-hidden rounded-4xl">
<Image
src={project.image}
src={project.imageSrc}
alt={project.title}
fill
className="h-auto w-full object-cover"
+5
View File
@@ -0,0 +1,5 @@
export interface IProjectCardProps {
imageSrc: string;
title: string;
link: string;
}
+1 -1
View File
@@ -20,7 +20,7 @@ const FormField: React.FC<FormFieldProps> = ({
name,
}) => {
const commonClass =
'w-full rounded-lg border border-gray-300 p-3 focus:ring-2 focus:ring-red-500 focus:outline-none';
'w-full rounded-lg border border-gray-100 p-3 focus:outline-none';
if (type === 'textarea') {
return (
+18
View File
@@ -0,0 +1,18 @@
import api from "@/lib/axios";
interface payload {
first_name: string,
last_name: string,
email: string,
phone: string,
message: string,
}
export async function setContact(payload:payload) {
return api
.post('/contact', payload)
.then(({ data }) => {
return Promise.resolve();
})
.catch((error) => Promise.reject(error));
}
+40
View File
@@ -0,0 +1,40 @@
'use server';
import { IProjectCardProps } from '@/components/pages/project/project';
import api from '@/lib/axios';
import { IResponse } from '@/models/response';
import { cookies } from 'next/headers';
export async function getProjectCategories() {
const cookiesStore = await cookies();
return api
.get('/project_categories', {
headers: {
Cookie: cookiesStore.toString(),
},
})
.then(({ data }) => {
return Promise.resolve(data.data);
})
.catch((error) => Promise.reject(error));
}
export async function getProjects(
categoryId: string,
page = 1,
): Promise<IResponse<IProjectCardProps[]>> {
const cookiesStore = await cookies();
return api
.get(`/project_categories/${categoryId}/projects`, {
headers: {
Cookie: cookiesStore.toString(),
},
params: { page },
})
.then(({ data }) => {
return Promise.resolve(data);
})
.catch((error) => Promise.reject(error));
}