Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

214 change add project form state managmant #221

Merged
merged 19 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions actions/addNewProject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use server';

import { IAddProjectForm } from '@/types/forms';

export const addNewProject = async (data: IAddProjectForm) => {
console.log(data);
};
2 changes: 1 addition & 1 deletion components/BeOurFriends/BeOurFriends.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const variants = {
};

const BeOurFriends = () => {
const t = useTranslations('components.home.beOurFriends');
const t = useTranslations('Components.home.beOurFriends');
const localLang = useLocale();
const direction = localLang == 'he' ? 'rtl' : 'ltr';

Expand Down
26 changes: 15 additions & 11 deletions components/Common/Inputs/FormTextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
import { FormFieldRegistration } from '@/types/forms';
import React from 'react';

type FormTextInputProps = {
interface FormTextInputProps extends FormFieldRegistration {
placeholder: string;
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
error?: string;
name: string;
}

const getErrorMessage = (errors: any, name: string) => {
return errors?.[name]?.message || '';
};

export const FormTextInput: React.FC<FormTextInputProps> = ({
placeholder,
value,
onChange,
error,
errors,
name,
register,
}) => {
const errorMessage = getErrorMessage(errors, name);
return (
<div>
<input
{...register(name, { required: true })}
name={name}
className={`mw-[462px] w-[100%] mx-auto h-14 p-2 block rounded-md focus:outline-non dark:bg-gray-700 bg-gray-200 ${
error && 'border-red-500'
errorMessage && 'border-red-500'
}`}
type="text"
placeholder={placeholder}
value={value}
onChange={onChange}
/>
{error && <p className="text-red-500 text-sm">{error}</p>}
{errorMessage && <p className="text-error">{errorMessage}</p>}
</div>
);
};
127 changes: 2 additions & 125 deletions components/Common/Modals/AddProjectmodal/AddProjectModal.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import React, { useState } from 'react';
import React from 'react';
import Modal from '../Modal';
import { z, ZodError } from 'zod';
import { FormTextInput } from '../../Inputs/FormTextInput';
import { FileUploader } from './FileUploader';
import { ProjectDescription } from './ProjectDescription';
import { TermsAndConditions } from './TermsAndConditions';
import { MustIncludeMessage } from './MustIncludeMessage';
import { ModalContent } from './ModalContent';

interface AddProjectModalProps<T> {
isOpen: boolean;
Expand All @@ -25,121 +20,3 @@ export const AddProjectModal = <T,>({
</div>
);
};
const schema = z.object({
name: z.string().min(2),
projectName: z.string().min(4),
email: z.string().email(),
});

interface ModalContentProps {
closeModal: any;
}

const ModalContent = ({ closeModal }: ModalContentProps) => {
type FormErrors = {
name?: string;
projectName?: string;
email?: string;
};

const [projectName, setProjectName] = useState('');
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [repoLink, setRepoLink] = useState('');
const [projectIcon, setProjectIcon] = useState('');
const [projectDescription, setProjectDescription] = useState('');
const [errors, setErrors] = useState<FormErrors>({});

const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};

const handleProjectNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setProjectName(e.target.value);
};

const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setEmail(e.target.value);
};

const handleRepoLinkChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setRepoLink(e.target.value);
};

const handleProjectDescriptionChange = (
e: React.ChangeEvent<HTMLTextAreaElement>
) => {
setProjectDescription(e.target.value);
};

const handleFileChange = (file: File) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
setProjectIcon(reader.result as string);
};
};

const handleSubmit = () => {
try {
schema.parse({ name, projectName, email });
setErrors({});
//TODO Add logic behind this later
} catch (error: any) {
if (error instanceof ZodError) {
const parsedErrors: { [key: string]: string } = {};

for (const { path, message } of error.errors) {
parsedErrors[path[0]] = message;
}
setErrors(parsedErrors);
}
}
};

return (
<div className="p-4 mt-24 dark:bg-[#0F1729] bg-gray-100 dark:text-white text-black rounded-[12px]">
<div className="flex justify-between mb-4">
<p className="text-xl font-bold text-right items-center">
בקשה להוספת פרויקט
</p>
<button onClick={closeModal}>X</button>
</div>

<div className="grid grid-cols-1 md:grid-cols-2 justify-center gap-4 max-w-[1100px] flex-wrap">
<FormTextInput
placeholder="שם מלא *"
value={name}
onChange={handleNameChange}
error={errors.name}
/>
<FormTextInput
placeholder="אימייל ליצירת קשר *"
value={email}
onChange={handleEmailChange}
error={errors.email}
/>
<FormTextInput
placeholder="קישור לריפו"
value={repoLink}
onChange={handleRepoLinkChange}
/>
<FormTextInput
placeholder="שם הפרוייקט *"
value={projectName}
onChange={handleProjectNameChange}
error={errors.projectName}
/>

<FileUploader onChange={handleFileChange} />
</div>

<ProjectDescription
projectDescription={projectDescription}
handleProjectDescriptionChange={handleProjectDescriptionChange}
/>
<TermsAndConditions closeModal={closeModal} handleSubmit={handleSubmit} />
<MustIncludeMessage />
</div>
);
};
25 changes: 14 additions & 11 deletions components/Common/Modals/AddProjectmodal/FileUploader.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import React from 'react';
import { UploadIcon } from './UploadIcon';
import { UseFormRegister, FieldValues } from 'react-hook-form';
import { FormFieldRegistration } from '@/types/forms';
import { useTranslations } from 'next-intl';

interface FileUploaderProps {
onChange: (file: File) => void;
interface FileUploaderProps extends FormFieldRegistration {
register: UseFormRegister<FieldValues>;
name: string;
}

export const FileUploader: React.FC<FileUploaderProps> = ({ onChange }) => {
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
onChange(file);
}
};
export const FileUploader: React.FC<FileUploaderProps> = ({
register,
name,
}) => {
const t = useTranslations('Maintainers.maintainerForm');

return (
<div className="flex flex-row items-center">
<p className="text-2xl whitespace-nowrap">לוגו (אם יש)</p>
<p className="text-2xl whitespace-nowrap">{t('logo')}</p>
<div className="ml-4 flex items-center dark:bg-gray-700 bg-gray-200 rounded-md m-auto">
<label htmlFor="file-input" className="cursor-pointer">
<input
{...register(name, { required: false })}
id="file-input"
type="file"
name={name}
className="hidden"
onChange={handleFileChange}
/>
<div className="flex justify-center items-center rounded-md max-w-[150px]">
<UploadIcon />
Expand Down
103 changes: 103 additions & 0 deletions components/Common/Modals/AddProjectmodal/ModalContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { addNewProject } from '@/actions/addNewProject';
import { IAddProjectForm } from '@/types/forms';
import { zodResolver } from '@hookform/resolvers/zod';
import { useLocale, useTranslations } from 'next-intl';
import { useForm, SubmitHandler, FieldValues } from 'react-hook-form';
import { z } from 'zod';
import { FormTextInput } from '../../Inputs/FormTextInput';
import { FileUploader } from './FileUploader';
import { MustIncludeMessage } from './MustIncludeMessage';
import { ProjectDescription } from './ProjectDescription';
import { TermsAndConditions } from './TermsAndConditions ';

interface ModalContentProps {
closeModal: () => void;
}

export const ModalContent = ({ closeModal }: ModalContentProps) => {
const t = useTranslations('Maintainers.maintainerForm');
const localLang = useLocale();
const direction = localLang == 'he' ? 'rtl' : 'ltr';

const schema = z.object({
fullName: z.string().min(2, t('fullNameError')),
email: z.string().email(t('wrongMailError')).min(1),
projectName: z.string().min(1, t('projectNameError')),
projectDescription: z.string(),
repoLink: z.string().optional(),
});
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: zodResolver(schema),
});

const onSubmit: SubmitHandler<IAddProjectForm> = async data => {
await addNewProject(data);
closeModal();
};

return (
<form
dir={direction}
onSubmit={handleSubmit(onSubmit as SubmitHandler<FieldValues>)}
className="p-4 mt-24 dark:bg-[#0F1729] bg-gray-100 dark:text-white text-black rounded-[12px]"
>
<div className="flex justify-between mb-4">
<p className="text-xl font-bold text-right items-center">
{t('requestAddProject')}
</p>
<button onClick={closeModal}>X</button>
</div>

<div className="grid grid-cols-1 md:grid-cols-2 justify-center gap-4 max-w-[1100px] flex-wrap">
<FormTextInput
placeholder={t('fullName')}
register={register}
errors={errors}
name={'fullName'}
/>
<FormTextInput
placeholder={t('email')}
register={register}
errors={errors}
name={'email'}
/>

<FormTextInput
placeholder={t('repoLink')}
register={register}
errors={errors}
name={'repoLink'}
/>

<FormTextInput
placeholder={t('projectDescription')}
register={register}
errors={errors}
name={'projectName'}
/>

<FileUploader register={register} name={'file'} />
</div>

<ProjectDescription
register={register}
name={'projectDescription'}
errors={errors}
/>

<MustIncludeMessage />
<TermsAndConditions closeModal={closeModal} />

<button
type="submit"
className="w-48 h-7 bg-indigo-600 text-white rounded-md hover:bg-indigo-700"
>
{t('send')}
</button>
</form>
);
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useTranslations } from 'next-intl';
import React from 'react';

export const MustIncludeMessage: React.FC = () => {
return (
<p className="text-error mt-2">
על מנת לשלוח בקשה לפרויקט חדש, יש למלא את סעיף שם מלא, שם פרוייקט
</p>
);
const t = useTranslations('Maintainers.maintainerForm');

return <p className="text-error mt-2">{t('mustReadMessage')}</p>;
};
Loading
Loading