Skip to content

Commit

Permalink
feat add project
Browse files Browse the repository at this point in the history
  • Loading branch information
himanshurajora committed Jan 2, 2024
1 parent 7ea80fb commit 0fa5420
Show file tree
Hide file tree
Showing 13 changed files with 410 additions and 28 deletions.
66 changes: 65 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"typegen": "npx pocketbase-typegen --env -o src/db.types.ts"
},
"dependencies": {
"@hookform/resolvers": "^3.3.3",
"@types/lodash": "^4.14.202",
"chart.js": "^4.4.1",
"lodash": "^4.17.21",
Expand All @@ -21,7 +22,9 @@
"quill": "^1.3.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-transition-group": "^4.4.5"
"react-hook-form": "^7.49.2",
"react-transition-group": "^4.4.5",
"yup": "^1.3.3"
},
"devDependencies": {
"@types/react": "^18.2.43",
Expand Down
190 changes: 190 additions & 0 deletions src/AddProjectDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { yupResolver } from '@hookform/resolvers/yup';
import { Button } from 'primereact/button';
import { Dialog } from 'primereact/dialog';
import { Editor } from 'primereact/editor';
import { InputText } from 'primereact/inputtext';
import { Message } from 'primereact/message';
import { MultiSelect } from 'primereact/multiselect';
import { Slider } from 'primereact/slider';
import { Dispatch, FC, SetStateAction, useContext } from 'react';
import { useForm } from 'react-hook-form';
import {
AddProjectDto,
validateAddProject,
} from './validation/addProjectValidation';
import { ProjectsLanguagesOptions } from './db.types';
import _ from 'lodash';
import { StoreContext } from './StoreContext';
export interface AddProjectFormProps {
visible: boolean;
setVisible: Dispatch<SetStateAction<boolean>>;
}
export const AddProjectForm: FC<AddProjectFormProps> = ({
visible,
setVisible,
}) => {
const { addProject } = useContext(StoreContext);
const {
register,
setValue,
formState: { errors, isValid, isValidating, isLoading, isSubmitting },
watch,
getValues,
reset,
} = useForm<AddProjectDto>({
mode: 'onChange',
resolver: yupResolver<AddProjectDto>(validateAddProject),
defaultValues: {
description: '',
github_repository: '',
home_page: '',
languages: [],
name: '',
skill_level: 10,
},
});

const handleFormSubmit = async () => {
try {
const object = getValues();
await addProject(object);
reset();
setVisible(false);
} catch (error) {
console.log(error);
}
};

const renderHeader = () => {
return (
<span className="ql-formats">
<b>Description</b>
</span>
);
};

const footerContent = (
<div className="mt-2">
<Button
label="Cancel"
icon="pi pi-times"
onClick={() => {
reset();
setVisible(false);
}}
className="p-button-text"
type="button"
/>
<Button
label="Add"
type="submit"
icon="pi pi-check"
onClick={handleFormSubmit}
disabled={isLoading || isSubmitting || !isValid || isValidating}
autoFocus
/>
</div>
);

return (
<Dialog
header="Add Project"
visible={visible}
style={{ width: '50vw' }}
onHide={() => setVisible(false)}
footer={footerContent}
maximizable
>
<form className="flex flex-col gap-3">
<div className="flex flex-col flex-wrap align-items-center gap-2">
<label htmlFor="name" className="p-sr-only">
Name
</label>
<InputText
placeholder="Name"
className="flex-1"
{...register('name')}
/>
{errors.name && (
<Message severity="error" text={errors.name.message} />
)}
</div>
<div className="flex flex-col flex-wrap align-items-center gap-2">
<label htmlFor="github_url" className="p-sr-only">
Github URL
</label>
<InputText
placeholder="Github URL"
{...register('github_repository')}
className="flex-1"
/>
{errors.github_repository && (
<Message severity="error" text={errors.github_repository.message} />
)}
</div>
<div className="flex flex-col flex-wrap align-items-center gap-2">
<label htmlFor="home_page" className="p-sr-only">
Home Page
</label>

<InputText
placeholder="Homepage"
className="flex-1"
{...register('home_page')}
/>
{errors.home_page && (
<Message severity="error" text={errors.home_page.message} />
)}
</div>
<MultiSelect
value={watch('languages')}
onChange={(e) => {
setValue('languages', e.value);
}}
options={_.map(ProjectsLanguagesOptions, (value, key) => {
return {
value,
label: key,
};
})}
filter
optionLabel="label"
placeholder="Select Languages"
maxSelectedLabels={3}
className="w-full md:w-20rem"
/>
<b className="ml-4">Skill Level:</b>
<Slider
className="mt-2 mx-6"
step={10}
onChange={(event) => {
if (typeof event.value === 'number')
setValue('skill_level', event.value / 10);
}}
value={watch('skill_level') * 10}
></Slider>
<div className="flex flex-row justify-between px-4 mt-1">
<b>0</b>
<b>10</b>
</div>
<Editor
headerTemplate={renderHeader()}
className="h-60"
placeholder="Write description"
min={50}
onTextChange={(event) => {
if (event.htmlValue) setValue('description', event.htmlValue);
}}
/>
<div className="flex flex-wrap flex-1 align-items-center gap-2">
<label htmlFor="description" className="p-sr-only">
Description
</label>
{errors.description && (
<Message severity="error" text={errors.description.message} />
)}
</div>
</form>
</Dialog>
);
};
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function App() {
setFilters,
globalSearch,
setGlobalSearch,
addProject,
} = useProjects();

return (
Expand All @@ -45,6 +46,7 @@ function App() {
setLoading: setProjectsLoading,
globalSearch,
setGlobalSearch,
addProject,
}}
>
<Navbar></Navbar>
Expand Down
Loading

0 comments on commit 0fa5420

Please sign in to comment.