اذهب إلى المحتوى

محمود سعداوي2

الأعضاء
  • المساهمات

    604
  • تاريخ الانضمام

  • تاريخ آخر زيارة

2 متابعين

المعلومات الشخصية

آخر الزوار

4714 زيارة للملف الشخصي

إنجازات محمود سعداوي2

عضو نشيط

عضو نشيط (3/3)

493

السمعة بالموقع

3

إجابات الأسئلة

  1. السلام عليكم. أود الإستفادة من ملاحظاتكم وتقييمكم محتوا وتصميما لموقعي الشخصي https://personal-portfolio-git-main-mahmouds-projects-1d23a688.vercel.app/en شكرا لكم
  2. السلام عليكم بالإعتماد على تجاربكم أود آراءكم في أفضل المكتبات التي تساعد العملاء في في إرال إيميلات عند الإطلاع على الموقعالشخصي شكرا
  3. السلام عليكم. أواجه مشكلة في استخدام next-intl مع Next.js 15 حيث يظهر لي خطأ متعلق بـ Hydration وآخر متعلق بالترويسات المسؤولة عن تحديد اللغة المحلية. الخطأ الأول: الخطأ الثاني: الخطأ يحدث عند محاولة استخدام الترويسة headers() بدون انتظار النتيجة بشكل صحيح. الخطأ الثالث: ملاحظات: لتوضيح أكثر، هذه هي تفاصيل الكود الذي أستخدمه: next.config.js: const nextConfig = { timeZone: "Africa/Tunis", }; const withNextIntl = require("next-intl/plugin")("./i18n.js"); module.exports = withNextIntl(nextConfig); i18n.js: import { getRequestConfig } from "next-intl/server"; export default getRequestConfig(async ({ locale }) => ({ // locale مشطبة messages: (await import(`./messages/${locale}.json`)).default, timeZone: "Africa/Tunis", })); middleware.js: import createMiddleware from "next-intl/middleware"; export default createMiddleware({ locales: ["en", "fr", "ar"], defaultLocale: "en", }); export const config = { matcher: ["/((?!api|_next|.*\\..*).*)"], }; app/[locale]/layout.js import { NextIntlClientProvider } from "next-intl"; import { AppProvider } from "@/context/AppContext"; import { Tajawal } from "next/font/google"; import { getLocale, getMessages } from "next-intl/server"; const tajawal = Tajawal({ subsets: ["arabic"], weight: ["300", "400", "500", "700"], }); export default async function RootLayout({ children }) { const locale = await getLocale(); const messages = getMessages() const direction = locale === "ar" ? "rtl" : "ltr"; const fontClassName = tajawal.className; return ( <html lang={locale} dir={direction}> <body className={fontClassName}> <NextIntlClientProvider locale={locale} messages={messages}> <AppProvider>{children}</AppProvider> </NextIntlClientProvider> </body> </html> ); } ملاحظات إضافية: لتجنب مشكلة الـ Hydration قمت بتجربة استخدام useEffect ولكن لم يعمل الكود كما يجب. شكرا
  4. السلام عليكم. أواجه مشكل في إستخدام next-intel مع nextjs15 حيث يظهر لي خطأ hydration وآخر حول الترويسات المسؤولة عن تحديد اللغة المحلية. الخطأ الأول Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used - A server/client branch `if (typeof window !== 'undefined')`. - Variable input such as `Date.now()` or `Math.random()` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. See more info here: https://nextjs.org/docs/messages/react-hydration-error - lang="en" - dir="ltr" - className="__className_f09b3f" الخطأ الثاني Error: Route "/[locale]" used `headers().get('X-NEXT-INTL-LOCALE')`. `headers()` should be awaited before using its value. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis at apply (file:///C:/Users/saadaoui/Desktop/portfolio/node_modules/next/dist/compiled/next-server/dist/compiled/react/cjs/react.react-server.development.js:888:26) at locale (webpack:///i18n.js?938b:3:41) at apply (file:///C:/Users/saadaoui/Desktop/portfolio/node_modules/next/dist/compiled/next-server/dist/compiled/react/cjs/react.react-server.development.js:888:26) at apply (file:///C:/Users/saadaoui/Desktop/portfolio/node_modules/next/dist/compiled/next-server/dist/compiled/react/cjs/react.react-server.development.js:888:26) at apply (file:///C:/Users/saadaoui/Desktop/portfolio/node_modules/next/dist/compiled/next-server/dist/compiled/react/cjs/react.react-server.development.js:888:26) at getLocale (webpack:///app/[locale]/layout.js?3ae2:12:33) 1 | import { getRequestConfig } from "next-intl/server"; 2 | > 3 | export default getRequestConfig(async ({ locale }) => ({ | ^ 4 | messages: (await import(`./messages/${locale}.json`)).default, 5 | timeZone: "Africa/Tunis", 6 | })); Error: INVALID_KEY: Namespace keys can not contain the character "." as this is used to express nesting. Please remove it or replace it with another character. Invalid keys: (app-pages-browser)/./context/AppContext.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next-intl/dist/esm/shared/NextIntlClientProvider.js (at _response._bundlerConfig), (app-pages-browser)/./app/[locale]/page.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/client-page.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/client-segment.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/render-from-template-context.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/lib/metadata/metadata-boundary.js (at _response._bundlerConfig) If you're migrating from a flat structure, you can convert your messages as follows: import {set} from "lodash"; const input = { "one.one": "1.1", "one.two": "1.2", "two.one.one": "2.1.1" }; const output = Object.entries(input).reduce( (acc, [key, value]) => set(acc, key, value), {} ); // Output: // // { // "one": { // "one": "1.1", // "two": "1.2" // }, // "two": { // "one": { // "one": "2.1.1" // } // } // } at nextCreate (file:///C:/Users/saadaoui/Desktop/portfolio/node_modules/next/dist/compiled/next-server/dist/compiled/react-dom/cjs/react-dom-server.edge.development.js:3911:19) at useMemo (file:///C:/Users/saadaoui/Desktop/portfolio/node_modules/next/dist/compiled/next-server/dist/compiled/react/cjs/react.development.js:1495:33) { code: 'INVALID_KEY', originalMessage: 'Namespace keys can not contain the character "." as this is used to express nesting. Please remove it or replace it with another character.\n' + '\n' + 'Invalid keys: (app-pages-browser)/./context/AppContext.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next-intl/dist/esm/shared/NextIntlClientProvider.js (at _response._bundlerConfig), (app-pages-browser)/./app/[locale]/page.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/client-page.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/client-segment.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/client/components/render-from-template-context.js (at _response._bundlerConfig), (app-pages-browser)/./node_modules/next/dist/lib/metadata/metadata-boundary.js (at _response._bundlerConfig)\n' + '\n' + "If you're migrating from a flat structure, you can convert your messages as follows:\n" + '\n' + 'import {set} from "lodash";\n' + '\n' + 'const input = {\n' + ' "one.one": "1.1",\n' + ' "one.two": "1.2",\n' + ' "two.one.one": "2.1.1"\n' + '};\n' + '\n' + 'const output = Object.entries(input).reduce(\n' + ' (acc, [key, value]) => set(acc, key, value),\n' + ' {}\n' + ');\n' + '\n' + '// Output:\n' + '//\n' + '// {\n' + '// "one": {\n' + '// "one": "1.1",\n' + '// "two": "1.2"\n' + '// },\n' + '// },\n' + '// "two": {\n' + '// "one": {\n' + '// "one": "2.1.1"\n' + '// }\n' + '// }\n' + '// }\n' } للتوضيح أكثر هذا الكود كاملا next.config.js const nextConfig = { timeZone: "Africa/Tunis", }; const withNextIntl = require("next-intl/plugin")("./i18n.js"); module.exports = withNextIntl(nextConfig); i18n.js import { getRequestConfig } from "next-intl/server"; export default getRequestConfig(async ({ locale }) => ({ messages: (await import(`./messages/${locale}.json`)).default, timeZone: "Africa/Tunis", })); middleware.js import createMiddleware from "next-intl/middleware"; export default createMiddleware({ locales: ["en", "fr", "ar"], defaultLocale: "en", }); export const config = { matcher: ["/((?!api|_next|.*\\..*).*)"], }; app/[locale]/layout.js import { NextIntlClientProvider } from "next-intl"; import { AppProvider } from "@/context/AppContext"; import { Tajawal } from "next/font/google"; import { getLocale, getMessages } from "next-intl/server"; const tajawal = Tajawal({ subsets: ["arabic"], weight: ["300", "400", "500", "700"], }); export default async function RootLayout({ children }) { const locale = await getLocale(); const messages = getMessages() const direction = locale === "ar" ? "rtl" : "ltr"; const fontClassName = tajawal.className; return ( <html lang={locale} dir={direction}> <body className={fontClassName}> <NextIntlClientProvider locale={locale} messages={messages}> <AppProvider>{children}</AppProvider> </NextIntlClientProvider> </body> </html> ); } ملاحظة لتفادي hydration قمت بتجربة الخطاف useEffect إلا أنه لم يتم تفعيل الكود بتاتا. شكرا لكم.
  5. شكرا ولكن ظهر هذا الخطأ node_modules\next-intl\dist\development\shared\NextIntlClientProvider.js (23:11) @ NextIntlClientProvider ⨯ Error: Failed to determine locale in `NextIntlClientProvider`, please provide the `locale` prop explicitly. See https://next-intl-docs.vercel.app/docs/configuration#locale at AsyncResource.runInAsyncScope (node:async_hooks:206:9) digest: "1085825041" 21 | 22 | if (!locale) { > 23 | throw new Error('Failed to determine locale in `NextIntlClientProvider`, please provide the `locale` prop explicitly.\n\nSee https://next-intl-docs.vercel.app/docs/configuration#locale' ); | ^ 24 | } 25 | return /*#__PURE__*/React__default.default.createElement(_IntlProvider.IntlProvider, _rollupPluginBabelHelpers.extends({ 26 | locale: locale GET /en 500 in 4488ms
  6. لايزال نفس الخطأ وأرجح أن يكون بسبب lang أو dir.
  7. السلام عليكم. الكود التالي import {NextIntlClientProvider} from 'next-intl'; import {getLocale, getMessages} from 'next-intl/server'; import { AppProvider } from "@/context/AppContext"; import { Tajawal } from "next/font/google"; const ubuntu = Tajawal({ subsets: ["arabic"], weight: ["300", "400", "500", "700"], }); export default async function RootLayout({ children }) { const locale = await getLocale(); const messages = await getMessages(); const direction = locale === "ar" ? "rtl" : "ltr"; return ( <html lang={locale} dir={direction}> <body className={ubuntu.className}> <NextIntlClientProvider messages={messages}> <AppProvider> {children} </AppProvider> </NextIntlClientProvider> </body> </html> ); } تسبب في هذا الخطأ Console Error Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used - A server/client branch `if (typeof window !== 'undefined')`. - Variable input such as `Date.now()` or `Math.random()` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. See more info here: https://nextjs.org/docs/messages/react-hydration-error - lang="en" - dir="ltr" - className="__className_f09b3f" Call Stack Next.js شكرا لكم
  8. السلام عليكم. أود أن أسأل علىcustum hook في react. ماهي مميزاتها وماهي فائدتها خاصة بعد النسخ الحديثة متى نستعملها هل يمكن تعويضها عبر إستعمال برامج لإدارة الحالة كredux او حتى react context شكرا.
  9. السلام عليكم. إعتمدت على react-quill لإرسال بيانات إلى قاعدة البيانات كما يلي "use client"; import React, { SetStateAction, useState } from 'react'; import dynamic from 'next/dynamic'; import 'react-quill/dist/quill.snow.css'; import { useTranslations } from 'next-intl'; const QuillEditor = dynamic(() => import('react-quill'), { ssr: false }); type DescriptionProps = { description: string, setDescription: React.Dispatch<React.SetStateAction<string>> } const Description = ({description, setDescription}: DescriptionProps) => { const t = useTranslations('Add Task') // const [description, setDescription] = useState<string>(''); const quillModules = { toolbar: [ [{ header: [1, 2, 3, false] }], ['bold', 'italic', 'underline', 'strike', 'blockquote'], [{ list: 'ordered' }, { list: 'bullet' }], ['link', 'image'], [{ align: [] }], [{ color: [] }], ['code-block'], ['clean'], ], }; const quillFormats = [ 'header', 'bold', 'italic', 'underline', 'strike', 'blockquote', 'list', 'bullet', 'link', 'image', 'align', 'color', 'code-block', ]; const handleEditorChange = (content: SetStateAction<string>) => { setDescription(content); }; return ( <div className=" bg-gradient-to-br from-white to-gray-100 dark:from-gray-800 dark:to-gray-900"> <h2 className="text-gray-800 dark:text-gray-300 font-medium mb-2"> {t('task_description')} </h2> <QuillEditor value={description} onChange={handleEditorChange} modules={quillModules} formats={quillFormats} className="w-full bg-gray-50 dark:bg-gray-800 border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-4 focus:ring-indigo-400 focus:border-indigo-500 transition-all text-gray-900 dark:text-gray-100 text-xl" /> </div> ); }; export default Description; المشكل الذي أواجهه هو أنه عند عرض البيانات لايتم عرضها كما أرسلتها (ul - ol ...) الكود <p className="mb-6 text-gray-700 dark:text-gray-300 text-justify" dangerouslySetInnerHTML={{ __html: task.description }} > {/* {task.description} */} </p> شكرا
  10. شكرا لكم. في الواقع وجدت الحل لكن بطريقة أخرى حيث قمت بفصل الform على الmodal.
  11. السلام عليكم. الرجاء المساعدة في تجاوز الخطأ التالي Error: Hydration failed because the initial UI does not match what was rendered on the server. See more info here: https://nextjs.org/docs/messages/react-hydration-error الكود 'use client' import { useTranslations } from 'next-intl'; import { useEffect, useState } from 'react'; import Description from './Description'; import { IoIosClose } from 'react-icons/io'; import { Task } from '@prisma/client'; import moment from 'moment'; interface UpdateTaskProps { task: Task } const UpdateTask = ({ task }: UpdateTaskProps) => { const t = useTranslations("Add Task"); const [isMounted, setIsMounted] = useState(false) // Handle open/close update modal const [updateTaskModal, setUpdateTaskModal] = useState(false) const openUpdateTaskModal = () => setUpdateTaskModal(true) const closeUpdateTaskModal = () => setUpdateTaskModal(false) // handle update modal const [title, setTitle] = useState(task.title); const [description, setDescription] = useState(task.description); const [from, setFrom] = useState(task.from); const [to, setTo] = useState(task.to); const [status, setStatus] = useState(task.status); useEffect(() => { setIsMounted(true); if (task) { setTitle(task.title || "") setDescription(task.description || "") setFrom(task.from || null); setTo(task.to || null); setStatus(task.status || "") } }, [task]); if (!isMounted) return null; return ( <div className="relative"> {/* Modal */} {updateTaskModal ? ( <div className="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50"> <div className="bg-white dark:bg-gray-800 rounded-lg p-6 w-11/12 md:w-3/4 shadow-xl overflow-auto max-h-[85vh]"> {/* {alert.type && <Toast alertText={alert.alertText} type={alert.type} />} */} {/* Close Button */} <button onClick={closeUpdateTaskModal} className="absolute top-1 right-1 bg-rubyRed p-1 rounded-full hover:bg-red-600" > <IoIosClose className="text-3xl text-white" /> </button> {/* Form */} <form // onSubmit={AddNewTask} className="space-y-6" > <div> <label className="block text-gray-800 dark:text-gray-300 font-medium mb-2"> {t("title")} </label> <input type="text" name="title" className="w-full p-3 border rounded-lg dark:bg-gray-700 dark:text-white" placeholder={t("enter_task_title")} value={title} onChange={(e) => setTitle(e.target.value)} /> </div> {/* Text editor Component */} <Description description={description} setDescription={setDescription} /> <div> <label className="block text-gray-800 dark:text-gray-300 font-medium mb-2"> {t("status")} </label> <select name="status" className="w-full p-3 border rounded-lg dark:bg-gray-700 dark:text-white" onChange={(e) => setStatus(e.target.value)} > <option value="NotStarted">{t("not_started")}</option> <option value="InProgress">{t("in_progress")}</option> <option value="Completed">{t("completed")}</option> </select> </div> <div className="grid grid-cols-2 gap-4"> <div> <label className="block text-gray-800 dark:text-gray-300 font-medium mb-2"> {t("from")} </label> <input type="date" name="from" className="w-full p-3 border rounded-lg dark:bg-gray-700 dark:text-white" value={from ? moment(from).format('YYYY-MM-DD') : ''} onChange={(e) => setFrom(new Date(e.target.value))} /> </div> <div> <label className="block text-gray-800 dark:text-gray-300 font-medium mb-2"> {t("to")} </label> <input type="date" name="to" className="w-full p-3 border rounded-lg dark:bg-gray-700 dark:text-white" value={to ? moment(to).format('YYYY-MM-DD') : ''} onChange={(e) => setTo(new Date(e.target.value))} /> </div> </div> <button type="submit" className="w-full bg-royalPurple text-white p-3 rounded-lg hover:bg-slate-700 transition" >{t('update')}</button> </form> </div> </div> ) : (<button onClick={openUpdateTaskModal} className="px-4 py-2 text-sm font-medium text-white bg-blue-500 rounded-md shadow-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-300 transition-all" > Update </button>)} </div> ) } export default UpdateTask شكرا لكم.
  12. شكرا مفس الشيء. هذه رسالة الخطأ Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale. The `notFound()` function will be called as a result.
  13. السلام عليكم. نبذة عن المشروع: عبارة عن قائمة مهام باستخدام nextjs typescript postegres prisma. المستخدم المسجل هو فقط من يمكنه إضافة مهمة بنية المشروع: src |_ app |_[locale] |_api |_taskaties middleware.ts i18n.ts taskaties/route.ts export async function GET (request: NextRequest) { try { const user = verifyToken(request) if (!user) { return NextResponse.json({message: "Access Denied!"}, {status: 401}) } const tasks = await prisma.task.findMany() return NextResponse.json(tasks, {status: 201}) } catch (error) { console.error("Error: ", error) return NextResponse.json({ message: "Internal Server Error" }, { status: 500 }) } } middleware.ts 1. export const config = { matcher: ['/((?!api|_next|.*\\..*).*)', '/api/taskaties/*], } export function middleware (request: NextRequest) { const token = request.cookies.get('jwtToken')?.value if (!token) { if (request.nextUrl.pathname.startsWith("/api/taskaties")) { return NextResponse.json( { message: 'No Token Provided, Access Denied!' }, { status: 401 } ) } } return NextResponse.next() } export default createMiddleware({ locales: ["en", "fr", "ar"], defaultLocale: "ar", }); في هذه الحالة يتم جلب المهام من قاعدة البيانات غير أنه لايتم التعرف على الواجهات ويتم إرجاع صفحة notFound 2. قمت بتعديل الكود ليصير كالتالي export const config = { matcher: ['/((?!api|_next|.*\\..*).*)'], } export function middleware(request: NextRequest) { const token = request.cookies.get('jwtToken')?.value; if (!token && request.nextUrl.pathname.startsWith("/api/taskaties")) { return NextResponse.json( { message: 'No Token Provided, Access Denied!' }, { status: 401 } ); } return createMiddleware({ locales: ["en", "fr", "ar"], defaultLocale: "en", })(request); } غير أ،ه في هذه الحالة عندما لا يكون لدي token يتم إرجاع `{message: "Access Denied!"}, {status: 401}` عوضا عن `{ message: 'No Token Provided, Access Denied!' }` وبالتالي لم يتم تفعيل الدوال الوسيطة التي تهدف للتحقق من المستخدم. شكرا
  14. نفس المشكل. هذا هو الكود كاملا. e.preventDefault(); setLoading(true); setAlert({ alertText: "", type: "" }); let errorMessage = ""; if (first_name === "") { errorMessage = "First Name is required"; } else if (last_name === "") { errorMessage = "Last Name is required"; } else if (email === "") { errorMessage = "Email is required"; } else if (password === "") { errorMessage = "Password is required"; } if (errorMessage) { setAlert({ alertText: errorMessage, type: "error" }); setLoading(false); return; } register form "use client"; import { useTranslations } from "next-intl"; import React, { FormEvent, useContext, useState } from "react"; import Toast from "../toast"; import { AppContext } from "@/context/AppContext"; const RegisterForm = () => { const t = useTranslations("Auth"); const context = useContext(AppContext); const [first_name, setFirst_name] = useState(""); const [last_name, setLast_name] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [loading, setLoading] = useState(false); if (!context) { throw new Error("AppContext must be used within an AppProvider"); } const { alert, setAlert } = context; const submitFormHandler = (e: FormEvent) => { e.preventDefault(); setLoading(true); setAlert({ alertText: "", type: "" }); let errorMessage = ""; if (first_name === "") { errorMessage = "First Name is required"; } else if (last_name === "") { errorMessage = "Last Name is required"; } else if (email === "") { errorMessage = "Email is required"; } else if (password === "") { errorMessage = "Password is required"; } if (errorMessage) { setAlert({ alertText: errorMessage, type: "error" }); setLoading(false); return; } }; return ( <div> {alert.alertText && ( <Toast alertText={alert.alertText} type={alert.type}/> )} <form onSubmit={submitFormHandler}> {/* First Name & Last Name Fields */} <div className="flex justify-between"> <div className="w-1/2 mx-2 mb-4"> <label className="text-white dark:text-coolGray"> {t("first_name")} <span className="text-rubyRed">*</span> </label> <input type="text" name="firstName" value={first_name} onChange={(e) => setFirst_name(e.target.value)} className={`w-full p-2 border ${first_name === "" ? "border-rubyRed" : "border-coolGray"} dark:border-white bg-white dark:bg-slateGray text-slateGray dark:text-white rounded-lg focus:outline-none focus:border-leafGreen`} /> </div> <div className="w-1/2 mx-2 mb-4"> <label className="text-white dark:text-coolGray"> {t("last_name")} <span className="text-rubyRed">*</span> </label> <input type="text" name="lastName" autoComplete="off" value={last_name} onChange={(e) => setLast_name(e.target.value)} className={`w-full p-2 border ${first_name === "" ? "border-rubyRed" : "border-coolGray"} dark:border-white bg-white dark:bg-slateGray text-slateGray dark:text-white rounded-lg focus:outline-none focus:border-leafGreen`} /> </div> </div> {/* Email Field */} <div className="mb-4"> <label className="text-white dark:text-coolGray"> {t("email")} <span className="text-rubyRed">*</span> </label> <input type="email" name="email" autoComplete="off" value={email} onChange={(e) => setEmail(e.target.value)} className={`w-full p-2 border ${email === "" ? "border-rubyRed" : "border-coolGray"} dark:border-white bg-white dark:bg-slateGray text-slateGray dark:text-white rounded-lg focus:outline-none focus:border-leafGreen`} /> </div> {/* Password Field */} <div className="mb-4"> <label className="text-white dark:text-coolGray"> {t("password")} <span className="text-rubyRed">*</span> </label> <input type="password" name="password" autoComplete="off" value={password} onChange={(e) => setPassword(e.target.value)} className={`w-full p-2 border ${password === "" ? "border-rubyRed" : "border-coolGray"} dark:border-white bg-white dark:bg-slateGray text-slateGray dark:text-white rounded-lg focus:outline-none focus:border-leafGreen`} /> </div> <p className="text-rubyRed mb-4">* {t('required')}</p> {/* Register Button */} <button type="submit" className="button button-block w-full py-2 text-lg font-semibold text-white bg-leafGreen hover:bg-coralRed rounded-lg transition-all duration-300" > {t("register")} </button> </form> </div> ); }; export default RegisterForm;
  15. السلام عليكم. عند إنشاء حساب جديد لابد على المستخدم إدخال كافة المعطيات (last name, first name, email, password) بحيث إدخال حقل فارغ يعني ظهور رسالة خطأ. في الكود التالي const context = useContext(AppContext); const [first_name, setFirst_name] = useState(""); const [last_name, setLast_name] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [loading, setLoading] = useState(false); if (!context) { throw new Error("AppContext must be used within an AppProvider"); } const { alert, setAlert } = context; const submitFormHandler = (e: FormEvent) => { e.preventDefault(); setLoading(true); // Validation if (first_name === "") { setAlert({ alertText: "First Name is required", type: "error" }); setLoading(false); return; } if (last_name === "") { setAlert({ alertText: "Last Name is required", type: "error" }); setLoading(false); return; } if (email === "") { setAlert({ alertText: "Email is required", type: "error" }); setLoading(false); return; } if (password === "") { setAlert({ alertText: "Password is required", type: "error" }); setLoading(false); return; } }; ***** return ( <div> {alert.alertText && ( <Toast alertText={alert.alertText} type={alert.type}/> )} <form onSubmit={submitFormHandler}> -------- </form> </div> ); عندما تكون كافة الحقول فارغة تظهر رسالة الخطأ الأولى، ولكن بعد ملئ الحقل الأول وترك بقية الحقول فارغة لاتظهر رسالة خطأ مجددا للتوضيح. AppContext "use client" import { Alert } from "@/utils/types"; import { createContext, ReactNode, useState } from "react" type Props = { children: ReactNode; }; type AppContextType = { darkMode: boolean, toggleMode: () => void, alert: Alert, setAlert: (alert: Alert) => void, } | null export const AppContext = createContext<AppContextType>({ darkMode: false, toggleMode: () => {}, alert: { type: "", alertText: "" }, setAlert: () => {}, }) export const AppProvider = ({ children }: Props) => { const [darkMode, setDarkMode] = useState(false) const [alert, setAlert] = useState<Alert>({ type: "", alertText: "" }); const toggleMode = () => { setDarkMode(!darkMode) } return ( <AppContext.Provider value = {{toggleMode, darkMode, alert, setAlert}}> <div className={`${darkMode && "dark"}`}> {children} </div> </AppContext.Provider> ) } شكرا لكم.
×
×
  • أضف...