Skip to content

Commit

Permalink
Merge pull request #207 from Maakaf/206-add-new-project-modal
Browse files Browse the repository at this point in the history
206 add new project modal
  • Loading branch information
Darkmift authored Mar 21, 2024
2 parents 0de65f9 + 5fbdb44 commit e66d9b4
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 27 deletions.
20 changes: 0 additions & 20 deletions components/Common/Button.tsx

This file was deleted.

24 changes: 24 additions & 0 deletions components/Common/Inputs/FormTextInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';

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

export const FormTextInput: React.FC<FormTextInputProps> = ({ placeholder, value, onChange, error }) => {
return (
<div>
<input
className={`mw-[462px] w-[100%] mx-auto h-14 p-2 block rounded-md focus:outline-non bg-gray-700 dark:bg-gray-200 ${error && 'border-red-500'}`}
type="text"
placeholder={placeholder}
value={value}
onChange={onChange}
/>
{error && <p className="text-red-500 text-sm">{error}</p>}
</div>
);
};

131 changes: 131 additions & 0 deletions components/Common/Modals/AddProjectmodal/AddProjectModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@

import React, { useState } 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';

interface AddProjectModalProps {
isOpen: boolean;
closeModal: () => void;
}

export const AddProjectModal: React.FC<AddProjectModalProps> = ({ isOpen, closeModal }) => {
return (
<div className='w-4/5'>
<Modal isOpen={isOpen} modalContent={<ModalContent closeModal={closeModal} />} />
</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 bg-[#0F1729] text-white dark:bg-gray-100 dark:text-black">
<p className="text-xl font-bold mb-4 text-right">בקשה להוספת פרויקט</p>

<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>
);
};
34 changes: 34 additions & 0 deletions components/Common/Modals/AddProjectmodal/FileUploader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { UploadIcon } from './UploadIcon';

interface FileUploaderProps {
onChange: (file: File) => void;
}

export const FileUploader: React.FC<FileUploaderProps> = ({ onChange }) => {
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
onChange(file);
}
};

return (
<div className='flex flex-row items-center'>
<p className='text-2xl whitespace-nowrap'>לוגו (אם יש)</p>
<div className="ml-4 flex items-center bg-gray-700 dark:bg-gray-200 rounded-md m-auto">
<label htmlFor="file-input" className="cursor-pointer">
<input
id="file-input"
type="file"
className="hidden"
onChange={handleFileChange}
/>
<div className='flex justify-center items-center rounded-md max-w-[150px]'>
<UploadIcon />
</div>
</label>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

export const MustIncludeMessage: React.FC = () => {
return (
<p className='text-error mt-2'>על מנת לשלוח בקשה לפרויקט חדש, יש למלא את סעיף שם מלא, שם פרוייקט</p>
);
};
20 changes: 20 additions & 0 deletions components/Common/Modals/AddProjectmodal/ProjectDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

interface ProjectDescriptionProps {
projectDescription: string;
handleProjectDescriptionChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
}

export const ProjectDescription: React.FC<ProjectDescriptionProps> = ({ projectDescription, handleProjectDescriptionChange }) => {
return (
<div className='w-[100%]'>
<p className="text-xl font-bold mb-4 mt-4 text-right">תיאור פרוייקט</p>
<textarea
className='h-56 bg-gray-700 dark:bg-gray-200 w-[100%] rounded-md'
placeholder="טקסט חופשי"
value={projectDescription}
onChange={handleProjectDescriptionChange}
/>
</div>
);
};
25 changes: 25 additions & 0 deletions components/Common/Modals/AddProjectmodal/TermsAndConditions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

interface TermsAndConditions {
closeModal: () => void;
handleSubmit: () => void;
}

export const TermsAndConditions: React.FC<TermsAndConditions> = ({ closeModal, handleSubmit }) => {
return (
<div className="flex justify-around flex-wrap mt-1">
<div className='flex justify-center'>
<input className='mb-1 ml-4' type='checkbox' />
<p> קראתי ואני מסכימ/ה <span className='underline'>לתנאי השימוש והצהרת הפרטיות *</span></p>
</div>
<div className='flex gap-4'>
<button className="mr-1" onClick={closeModal}>ביטול</button>
<button
className="w-48 h-7 bg-indigo-600 text-white rounded-md hover:bg-indigo-700"
onClick={handleSubmit}
>
שליחה
</button>
</div>
</div>
);
};
29 changes: 29 additions & 0 deletions components/Common/Modals/AddProjectmodal/UploadIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export const UploadIcon = () => (
<svg
width="41"
height="41"
viewBox="0 0 41 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="stroke-gray-300 dark:stroke-[#dark] w-72 rounded-md mw-[100%]"
>
<path
d="M35.875 25.625V32.4583C35.875 33.3645 35.515 34.2335 34.8743 34.8743C34.2335 35.515 33.3645 35.875 32.4583 35.875H8.54167C7.63551 35.875 6.76647 35.515 6.12572 34.8743C5.48497 34.2335 5.125 33.3645 5.125 32.4583V25.625"
strokeWidth="3.41667"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M29.0416 13.6667L20.5 5.125L11.9583 13.6667"
strokeWidth="3.41667"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M20 5V25.5"
strokeWidth="3.41667"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
26 changes: 26 additions & 0 deletions components/Common/Modals/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client'

import React, { ReactNode } from 'react';

interface ModalProps {
isOpen: boolean;
modalContent: ReactNode
}

const Modal = ({ isOpen,modalContent } : ModalProps) => {
if (!isOpen) return null;

return (
<div className="fixed z-10 inset-0 overflow-y-auto">
<div className="flex items-center justify-center min-h-screen">
<div className="relative rounded-sm shadow-lg">
<div>
{modalContent}
</div>
</div>
</div>
</div>
);
};

export default Modal;
20 changes: 18 additions & 2 deletions components/Maintainers/MaintainerForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import Button from '../Common/Button';
'use client'

import React, { useState } from 'react';
import { AddProjectModal } from '../Common/Modals/AddProjectmodal/AddProjectModal';

const MaintainerForm = () => {
const [isModalOpen, setIsModalOpen] = useState(false);

const openModal = () => {
setIsModalOpen(true);
};

return (
<div className="px-4 mx-auto text-center text-[#020616] dark:text-[#F8FAFC]">
<h1 className="mb-3 font-black text-4xl mx-auto md:text-5xl">
Expand All @@ -18,7 +27,14 @@ const MaintainerForm = () => {
</p>
</div>

<Button className="mx-auto font-inter my-11" />
<AddProjectModal isOpen={isModalOpen} closeModal={() => setIsModalOpen(false)} />

<button
className="text-xs mx-auto mb-9 btn rounded-full px-7 py-2 flex items-center justify-center gap-2 dark:hover:bg-purple-200 dark:hover:text-darkText transition-all w-48"
onClick={openModal}
>
טופס הצטרפות
</button>
</div>
);
};
Expand Down
Loading

0 comments on commit e66d9b4

Please sign in to comment.