add: chat page locale and messaging functionality

This commit is contained in:
Mahyar Khanbolooki
2025-07-27 18:15:26 +03:30
parent 83cbe43d0e
commit ffc95cc007
3 changed files with 93 additions and 85 deletions
+70 -68
View File
@@ -1,107 +1,109 @@
'use client'; 'use client';
import { ef } from '@/lib/helpers/utfNumbers';
import { EmojiHappy, Microphone2, Paperclip2 } from 'iconsax-react'; import { EmojiHappy, Microphone2, Paperclip2 } from 'iconsax-react';
import React from 'react' import React, { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next';
type Props = object type Props = object
type MessageModel = {
type: "sender" | "receiver",
senderName: string,
content: string,
date: string,
time: string,
}
function ChatIndex({ }: Props) { function ChatIndex({ }: Props) {
const { t } = useTranslation('chat');
const [messages, setMessages] = useState<Array<MessageModel>>([
{
type: "sender",
senderName: "علی مصلحی",
content: 'لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است',
date: '1403/09/30',
time: '10:07'
},
{
type: 'receiver',
senderName: 'سیما فرهادی',
content: 'لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است',
date: '1403/09/30',
time: '10:07'
},
]);
const addMessageOutgoing = (model: MessageModel) => {
setMessages((previous) => {
return [...previous, model]
})
}
const submitMessage = async (formData: FormData) => { const submitMessage = async (formData: FormData) => {
console.log(formData.get('textMessage')) const content = formData.get('textMessage');
if (!content) return;
const model: MessageModel = {
type: 'sender',
senderName: 'علی مصلحی',
content: String(content),
date: '1403/09/30',
time: '10:07'
}
addMessageOutgoing(model);
}; };
const messagesMemo = useMemo(() => messages, [messages]);
return ( return (
<section className="flex flex-col h-full pt-6"> <section className="flex flex-col h-full pt-6">
<h1 className="font-medium">علی مصلحی</h1> <h1 className="font-medium">علی مصلحی</h1>
<div className="bg-container rounded-[30px] mt-6 flex flex-col flex-1 px-6 pt-7 pb-8 overflow-hidden"> <div className="bg-container rounded-[30px] flex flex-col justify-between mt-6 flex-1 px-6 pt-7 pb-8 overflow-hidden">
<div className="flex-1 overflow-y-auto"> <div className="overflow-y-auto flex flex-col-reverse">
<ul className="grid gap-6 pb-6 "> <ul className="grid gap-6 pb-6 ">
<li className='bg-[#F6F7FA] rounded-[30px] rounded-tr-none p-6'> {messagesMemo.map((v, i) => {
if (v.type === "sender") {
return (
<li key={i} className='bg-[#F6F7FA] rounded-[30px] rounded-tr-none p-6'>
<article> <article>
<p className='text-xs2'> <p className='text-xs2'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است {v.content}
</p> </p>
<span dir='ltr' className='text-[11px] float-end text-disabled-text mt-2.5'> <span dir='ltr' className='text-[11px] float-end text-disabled-text mt-2.5'>
10:07 | 1403/09/30 {ef(`${v.time} | ${v.date}`)}
</span> </span>
</article> </article>
</li> </li>
)
<li className='bg-[#EBEDF5] rounded-[30px] rounded-tl-none p-6'> }
else {
return (
<li key={i} className='bg-[#EBEDF5] rounded-[30px] rounded-tl-none p-6'>
<article> <article>
<h6 className='text-xs font-medium'> <h6 className='text-xs font-medium'>
سیما فرهادی {v.senderName}
</h6> </h6>
<p className='text-xs2 mt-2.5'> <p className='text-xs2 mt-2.5'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، {v.content}
</p> </p>
<span dir='ltr' className='text-[11px] float-end text-disabled-text mt-2.5'> <span dir='ltr' className='text-[11px] float-end text-disabled-text mt-2.5'>
10:07 | 1403/09/30 {ef(`${v.time} | ${v.date}`)}
</span>
</article>
</li>
<li className='bg-[#F6F7FA] rounded-[30px] rounded-tr-none p-6'>
<article>
<p className='text-xs2'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است
</p>
<span dir='ltr' className='text-[11px] float-end text-disabled-text mt-2.5'>
10:07 | 1403/09/30
</span>
</article>
</li>
<li className='bg-[#EBEDF5] rounded-[30px] rounded-tl-none p-6'>
<article>
<h6 className='text-xs font-medium'>
سیما فرهادی
</h6>
<p className='text-xs2 mt-2.5'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است،
</p>
<span dir='ltr' className='text-[11px] float-end text-disabled-text mt-2.5'>
10:07 | 1403/09/30
</span>
</article>
</li>
<li className='bg-[#F6F7FA] rounded-[30px] rounded-tr-none p-6'>
<article>
<p className='text-xs2'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است
</p>
<span dir='ltr' className='text-[11px] float-end text-disabled-text mt-2.5'>
10:07 | 1403/09/30
</span>
</article>
</li>
<li className='bg-[#EBEDF5] rounded-[30px] rounded-tl-none p-6'>
<article>
<h6 className='text-xs font-medium'>
سیما فرهادی
</h6>
<p className='text-xs2 mt-2.5'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است،
</p>
<span dir='ltr' className='text-[11px] float-end text-disabled-text mt-2.5'>
10:07 | 1403/09/30
</span> </span>
</article> </article>
</li> </li>
)
}
})}
</ul> </ul>
</div> </div>
<section aria-labelledby="ارسال پیام" className="w-full"> <section aria-labelledby={t("InputMessage.AriaLabelBy")} className="w-full">
<form <form
action={submitMessage} action={submitMessage}
className="focus-within:outline-blue-400 outline outline-transparent transition-colors duration-100 flex items-center gap-0 bg-transparent border border-[#D0D0D0] h-12 rounded-xl py-2.5 px-2" className="focus-within:outline-blue-400 outline outline-transparent transition-colors duration-100 flex items-center gap-0 bg-transparent border border-[#D0D0D0] h-12 rounded-xl py-2.5 px-2"
@@ -115,7 +117,7 @@ function ChatIndex({ }: Props) {
autoComplete="off" autoComplete="off"
className="w-full text-[11px] h-full outline-none ms-1" className="w-full text-[11px] h-full outline-none ms-1"
type="text" type="text"
placeholder="پیام خود را بنویسید" placeholder={t("InputMessage.Placeholder")}
/> />
<button type="button" className="active:bg-neutral-100 transition-colors duration-150 rounded-full p-1.5"> <button type="button" className="active:bg-neutral-100 transition-colors duration-150 rounded-full p-1.5">
<EmojiHappy className="stroke-disabled2" size={20} /> <EmojiHappy className="stroke-disabled2" size={20} />
+1 -1
View File
@@ -11,7 +11,7 @@ export const metadata: Metadata = {
description: 'Webapp dashboard', description: 'Webapp dashboard',
} }
const i18nNamespaces = ['common', 'menu', 'orders', 'auth', "rating"]; const i18nNamespaces = ['common', 'menu', 'orders', 'auth', "rating", "chat"];
export default async function RootLayout({ export default async function RootLayout({
children, children,
+6
View File
@@ -0,0 +1,6 @@
{
"InputMessage": {
"AriaLabelBy": "ارسال پیام",
"Placeholder": "پیام خود را بنویسید"
}
}