From 2fddcf9ddd94ed865388790f3c4e6359b9aba146 Mon Sep 17 00:00:00 2001 From: Jakub K Date: Wed, 27 Mar 2024 19:10:37 +0100 Subject: [PATCH 1/7] zmiana adresow --- .drone.yml | 6 +++--- deployment.yml | 2 +- src/components/AddJobListing.jsx | 4 ++-- src/components/ImageUpload.jsx | 2 +- src/components/JobOfferContent.jsx | 2 +- src/components/WorkApp.jsx | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.drone.yml b/.drone.yml index 705d800..5b51c2c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -5,9 +5,9 @@ name: default steps: - name: build commands: - - docker build --no-cache -t izaac-frontend:latest . - - docker tag izaac-frontend:latest registry.izaac.pl:5000/izaac-frontend:latest - - docker push registry.izaac.pl:5000/izaac-frontend:latest + - docker build --no-cache -t izaac-frontend-master:latest . + - docker tag izaac-frontend-master:latest registry.izaac.pl:5000/izaac-frontend:latest + - docker push registry.izaac.pl:5000/izaac-frontend-master:latest - name: delete environment: diff --git a/deployment.yml b/deployment.yml index 3bd9201..7ff099e 100644 --- a/deployment.yml +++ b/deployment.yml @@ -31,7 +31,7 @@ spec: spec: containers: - name: izaac-frontend - image: registry.izaac.pl:5000/izaac-frontend:latest + image: registry.izaac.pl:5000/izaac-frontend-master:latest ports: - containerPort: 80 volumeMounts: diff --git a/src/components/AddJobListing.jsx b/src/components/AddJobListing.jsx index e321545..e7966f7 100644 --- a/src/components/AddJobListing.jsx +++ b/src/components/AddJobListing.jsx @@ -53,7 +53,7 @@ const AddJobListing = () => { const handleSubmit = async () => { try { - const response = await axios.post('http://izaac.izaac.pl/api/jobposting/joboffers/', formData); + const response = await axios.post('https://izaac.knck.pl/api/jobposting/joboffers/', formData); console.log('Data posted:', response.data); nextStep(); } catch (error) { @@ -63,7 +63,7 @@ const AddJobListing = () => { const getSkills = async () => { try { - const response = await axios.get('http://izaac.izaac.pl/api/jobposting/skills/'); + const response = await axios.get('https://izaac.knck.pl/api/jobposting/skills/'); setSkills(response.data.sort((a, b) => a.skill_name.localeCompare(b.skill_name))); } catch (error) { diff --git a/src/components/ImageUpload.jsx b/src/components/ImageUpload.jsx index b2b9572..0a7643c 100644 --- a/src/components/ImageUpload.jsx +++ b/src/components/ImageUpload.jsx @@ -30,7 +30,7 @@ const ImageUpload = ({setFormData, data}) => { formData.append('company_logo', imageFile); formData.append('company_name', data.company_name) try { - const response = await axios.post('http://izaac.izaac.pl/api/jobposting/companylogo/', formData, { + const response = await axios.post('https://izaac.knck.pl/api/jobposting/companylogo/', formData, { headers: { "Content-Type": 'multipart/form-data' } diff --git a/src/components/JobOfferContent.jsx b/src/components/JobOfferContent.jsx index 433cc2f..857e32e 100644 --- a/src/components/JobOfferContent.jsx +++ b/src/components/JobOfferContent.jsx @@ -8,7 +8,7 @@ const JobOfferContent = ({ id, skills }) => { const fetchJobOfferById = async (jobId) => { try { - const response = await axios.get(`http://izaac.izaac.pl/api/jobposting/joboffers/${jobId}`); + const response = await axios.get(`https://izaac.knck.pl/api/jobposting/joboffers/${jobId}`); setJobOffer(response.data); } catch (error) { console.error('Failed to fetch job offer:', error); diff --git a/src/components/WorkApp.jsx b/src/components/WorkApp.jsx index b6c1c61..9f062d8 100644 --- a/src/components/WorkApp.jsx +++ b/src/components/WorkApp.jsx @@ -50,7 +50,7 @@ const WorkApp = () => { const getOgloszenia = async () => { try { - const response = await axios.get('http://izaac.izaac.pl/api/jobposting/joboffers_list/'); + const response = await axios.get('https://izaac.knck.pl/api/jobposting/joboffers_list/'); const data = response.data; setOgloszenia(data); // console.log(data); @@ -65,7 +65,7 @@ const WorkApp = () => { const getSkills = async () => { try { - const response = await axios.get(`http://izaac.izaac.pl/api/jobposting/skills/`); + const response = await axios.get(`https://izaac.knck.pl/api/jobposting/skills/`); const data = response.data; setSkills(data); console.log(data); From b3adb4f8fb748098a1d14b034da935312dce5a5f Mon Sep 17 00:00:00 2001 From: Jakub K Date: Wed, 27 Mar 2024 19:13:32 +0100 Subject: [PATCH 2/7] zmiana adresow --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 5b51c2c..e2eef6d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,7 +6,7 @@ steps: - name: build commands: - docker build --no-cache -t izaac-frontend-master:latest . - - docker tag izaac-frontend-master:latest registry.izaac.pl:5000/izaac-frontend:latest + - docker tag izaac-frontend-master:latest registry.izaac.pl:5000/izaac-frontend-master:latest - docker push registry.izaac.pl:5000/izaac-frontend-master:latest - name: delete From ee75b0f2eb934b18bbfe1fee1b4502ded31ceb9f Mon Sep 17 00:00:00 2001 From: Jakub Kaniecki Date: Fri, 7 Jun 2024 19:41:53 +0200 Subject: [PATCH 3/7] cicd --- deployment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment.yml b/deployment.yml index 7ff099e..1b103b1 100644 --- a/deployment.yml +++ b/deployment.yml @@ -31,7 +31,7 @@ spec: spec: containers: - name: izaac-frontend - image: registry.izaac.pl:5000/izaac-frontend-master:latest + image: registry.knck.pl:5000/izaac-frontend-master:latest ports: - containerPort: 80 volumeMounts: From 7020cdeb4e9bd3163ae9b03d250548b6ec61fde2 Mon Sep 17 00:00:00 2001 From: Jakub Kaniecki Date: Fri, 7 Jun 2024 20:33:48 +0200 Subject: [PATCH 4/7] jakies tam poprawki --- package-lock.json | 28 +++++++++++++++++++++++++++ src/components/JobOfferContent.jsx | 5 +++-- src/components/SkillRender.jsx | 2 +- src/components/StepFourJoblisting.jsx | 23 ++++++++++++---------- src/components/TextDivider.jsx | 2 +- 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3cfc64a..0d197b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@ckeditor/ckeditor5-build-classic": "^40.0.0", "@ckeditor/ckeditor5-build-multi-root": "^40.0.0", "@ckeditor/ckeditor5-react": "^6.1.0", + "axios": "^0.24.0", "dompurify": "^3.0.6", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -1723,6 +1724,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "dependencies": { + "follow-redirects": "^1.14.4" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2668,6 +2677,25 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", diff --git a/src/components/JobOfferContent.jsx b/src/components/JobOfferContent.jsx index 857e32e..1e50a49 100644 --- a/src/components/JobOfferContent.jsx +++ b/src/components/JobOfferContent.jsx @@ -1,8 +1,9 @@ import React, { useEffect, useState } from 'react'; import axios from 'axios'; import DOMPurify from 'dompurify'; -import SkillRender from './SkillRender'; // Ensure this import is correctly pointing to your SkillRender component +import SkillRender from './SkillRender'; +// eslint-disable-next-line react/prop-types const JobOfferContent = ({ id, skills }) => { const [jobOffer, setJobOffer] = useState(null); @@ -48,7 +49,7 @@ const JobOfferContent = ({ id, skills }) => { <>

{jobOffer.name} w {jobOffer.company_name}

- {jobOffer.skill_levels.map((skillLevel) => { + {jobOffer.skill_levels && jobOffer.skill_levels.map((skillLevel) => { const skill = skills.find((s) => s.id === parseInt(skillLevel.skill_id)); return skill ? ( diff --git a/src/components/SkillRender.jsx b/src/components/SkillRender.jsx index 384c9f3..33d1aa1 100644 --- a/src/components/SkillRender.jsx +++ b/src/components/SkillRender.jsx @@ -31,7 +31,7 @@ const SkillRender = ({key, skill, level,}) => { return ( -
+

{skill}

diff --git a/src/components/StepFourJoblisting.jsx b/src/components/StepFourJoblisting.jsx index c0a12e4..9e87d33 100644 --- a/src/components/StepFourJoblisting.jsx +++ b/src/components/StepFourJoblisting.jsx @@ -7,7 +7,7 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => {
-
+
Imię @@ -21,8 +21,9 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => { id="first_name" onChange={handleChange("first_name")} placeholder="Twoje imię..." - className={`border-b-2 px-4 my-2 ${styles.paragraph}`} + className={`px-4 mt-2 ${styles.paragraph}`} /> +
@@ -37,8 +38,9 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => { id="last_name" onChange={handleChange("last_name")} placeholder="Twoje nazwisko..." - className={`border-b-2 px-4 my-2 ${styles.paragraph}`} + className={`px-4 mt-2 ${styles.paragraph}`} /> +
@@ -53,15 +55,15 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => { id="contact_email" onChange={handleChange("contact_email")} placeholder="Adres mailowy..." - className={`border-b-2 px-4 my-2 ${styles.paragraph}`} + className={`px-4 mt-2 ${styles.paragraph}`} /> +
-
+
Nazwa firmy *
-
{ onChange={handleChange("company_name")} id="company_name" placeholder="Wpisz nazwę firmy..." - className={`border-b-2 px-4 mr-12 my-2 ${styles.paragraph} col-span-2 `} + className={`px-4 mt-2 ${styles.paragraph}`} /> -
+
@@ -88,8 +90,9 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => { onChange={handleChange("vat_number")} id="vat_number" placeholder="Wpisz nip..." - className={`border-b-2 px-4 my-2 ${styles.paragraph} `} - /> + className={`px-4 mt-2 ${styles.paragraph}`} + /> +
diff --git a/src/components/TextDivider.jsx b/src/components/TextDivider.jsx index cdf4c84..e1a9f94 100644 --- a/src/components/TextDivider.jsx +++ b/src/components/TextDivider.jsx @@ -4,7 +4,7 @@ const TextDivider = ({text }) => { return (
-

+

{text}

From 256bd8a0ee04d067922bb7eafcf782fb48bd22ca Mon Sep 17 00:00:00 2001 From: Jakub Kaniecki Date: Mon, 8 Jul 2024 20:52:43 +0200 Subject: [PATCH 5/7] dodanie nowych komponentow oraz dodanie walidacji propTypes --- index.html | 2 +- src/App.jsx | 27 ++--- src/components/AddJobListing.jsx | 2 +- src/components/Category.jsx | 9 +- src/components/EmployerPanel.jsx | 2 +- src/components/Filter.jsx | 140 +++++++++++++++++++++---- src/components/Home.jsx | 2 +- src/components/ImageUpload.jsx | 9 +- src/components/JobOfferContent.jsx | 2 +- src/components/ListingSmall.jsx | 28 +++-- src/components/Login.jsx | 7 +- src/components/Mininav.jsx | 7 +- src/components/NavBar.jsx | 5 +- src/components/Register.jsx | 7 +- src/components/Salary.jsx | 17 ++- src/components/Search.jsx | 60 +++++++++-- src/components/SelectedSkill.jsx | 10 +- src/components/Selector.jsx | 35 +++++++ src/components/SkillList.jsx | 6 +- src/components/SkillRender.jsx | 9 +- src/components/SkillsSelector.jsx | 10 +- src/components/StepFourJoblisting.jsx | 12 ++- src/components/StepOneJoblisting.jsx | 10 +- src/components/StepThreeJoblisting.jsx | 12 ++- src/components/StepTwoJoblisting.jsx | 17 ++- src/components/Success.jsx | 2 +- src/components/TextDivider.jsx | 8 +- src/components/WorkApp.jsx | 126 +++++++++++----------- src/consts/index.js | 4 +- src/index.css | 116 ++++++++++---------- tailwind.config.js | 2 +- 31 files changed, 491 insertions(+), 214 deletions(-) create mode 100644 src/components/Selector.jsx diff --git a/index.html b/index.html index b7a44d1..586bd2f 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ - izaac frontend + Izaac - praca dla inżynierów
diff --git a/src/App.jsx b/src/App.jsx index 9905387..1be36b2 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -7,38 +7,29 @@ import { Route, Routes } from "react-router-dom"; import Contact from "./components/Contact"; import Mininav from "./components/Mininav"; import AddJobListing from "./components/AddJobListing"; -import { useState, useEffect } from "react"; -import axios from "axios"; -import EmployerPanel from "./components/EmployerPanel"; function App() { - const loc = () => { - if (location.pathname.startsWith("work/jobposting")) { - return ""; - } else { - return "overflow-hidden"; - } - }; return ( -
-
- -
+
+
+ {/* */} +
-
+
} /> } /> - } /> + } /> } /> - } /> - } /> + } /> + } /> + {/* } /> */} {/* Add more routes as needed */}
diff --git a/src/components/AddJobListing.jsx b/src/components/AddJobListing.jsx index e7966f7..25ce10c 100644 --- a/src/components/AddJobListing.jsx +++ b/src/components/AddJobListing.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react' +import { useState, useEffect } from 'react' import StepOneJoblisting from './StepOneJoblisting'; import StepTwoJoblisting from './StepTwoJoblisting'; import StepThreeJoblisting from './StepThreeJoblisting'; diff --git a/src/components/Category.jsx b/src/components/Category.jsx index 0d00e66..6c1d314 100644 --- a/src/components/Category.jsx +++ b/src/components/Category.jsx @@ -1,4 +1,4 @@ -import React from 'react' +import propTypes from 'prop-types' const Category = (props) => { return ( @@ -15,4 +15,11 @@ const Category = (props) => { ) } +Category.propTypes = { + name: propTypes.string, + func: propTypes.func, + small: propTypes.bool, + last: propTypes.bool +} + export default Category diff --git a/src/components/EmployerPanel.jsx b/src/components/EmployerPanel.jsx index 29c2569..2eb63d1 100644 --- a/src/components/EmployerPanel.jsx +++ b/src/components/EmployerPanel.jsx @@ -1,4 +1,4 @@ -import React from "react"; + import { ogloszenia } from "../consts"; import ListingSmall from "./ListingSmall"; import { useState } from "react"; diff --git a/src/components/Filter.jsx b/src/components/Filter.jsx index 06ecb69..0a4dd71 100644 --- a/src/components/Filter.jsx +++ b/src/components/Filter.jsx @@ -1,30 +1,128 @@ -import React from 'react' + import Search from './Search' - - +import { useEffect, useState } from 'react'; +import { categories, work_from_home, employment_types } from '../consts'; +import propTypes from 'prop-types'; +import Selector from './Selector'; const Filter = (props) => { - if (!props.isOpen) return null; - return ( -
- - - - + useEffect(() => { + console.log(props.searchQuery) + console.log(selectedCategories) + console.log(selectedWorkFromHome) + console.log(selectedEmploymentTypes) + console.log(valueminSalary) + }, [props.searchQuery]); - +
+ + + + + + + + + +
) -} +}; -export default Filter +Filter.propTypes = { + isOpen: propTypes.bool, + searchQuery: propTypes.object, + setSearchQuery: propTypes.func, + categories: propTypes.array, + clearSearchQuery: propTypes.func, + onClick: propTypes.func +}; + +export default Filter; diff --git a/src/components/Home.jsx b/src/components/Home.jsx index e633d2f..53a2fc7 100644 --- a/src/components/Home.jsx +++ b/src/components/Home.jsx @@ -1,4 +1,4 @@ -import React from 'react' + import styles from '../style' const Home = () => { return ( diff --git a/src/components/ImageUpload.jsx b/src/components/ImageUpload.jsx index 0a7643c..f4612e9 100644 --- a/src/components/ImageUpload.jsx +++ b/src/components/ImageUpload.jsx @@ -1,7 +1,7 @@ -import React, { useState, useRef, useEffect } from 'react'; +import { useState, useRef, useEffect } from 'react'; import { placeholderImage } from '../assets'; import axios from 'axios'; - +import propTypes from 'prop-types'; const ImageUpload = ({setFormData, data}) => { const [imageSrc, setImageSrc] = useState(placeholderImage); @@ -83,4 +83,9 @@ const ImageUpload = ({setFormData, data}) => { ); }; +ImageUpload.propTypes = { + setFormData: propTypes.func, + data: propTypes.object +}; + export default ImageUpload; diff --git a/src/components/JobOfferContent.jsx b/src/components/JobOfferContent.jsx index dc73c5a..2cbdd58 100644 --- a/src/components/JobOfferContent.jsx +++ b/src/components/JobOfferContent.jsx @@ -9,7 +9,7 @@ const JobOfferContent = ({ id, skills }) => { const fetchJobOfferById = async (jobId) => { try { - const response = await axios.get(`https://izaac.knck.pl/api/jobposting/joboffers/${jobId}`); + const response = await axios.get(`https://izaac.knck.pl/api/jobposting/joboffers/${jobId}/?format=json`); setJobOffer(response.data); } catch (error) { console.error('Failed to fetch job offer:', error); diff --git a/src/components/ListingSmall.jsx b/src/components/ListingSmall.jsx index d41da5e..2e0f147 100644 --- a/src/components/ListingSmall.jsx +++ b/src/components/ListingSmall.jsx @@ -1,11 +1,12 @@ -import React from 'react' -import { IzaacLOGO } from '../assets' -const ListingSmall = ({ id, name, company_name, min_salary, max_salary, require_salary, index, onClick, _class, image }) => { +import { IzaacLOGO } from '../assets' +import propTypes from 'prop-types' + +const ListingSmall = ({ id, name, company_name, min_salary, max_salary, require_salary, index, onClick, _class, image, selected, blur }) => { return (
@@ -14,7 +15,7 @@ const ListingSmall = ({ id, name, company_name, min_salary, max_salary, require_

{name}

-

{company_name}

+

{company_name}

{/* Wyświetlenie wynagrodzenia pod nazwą, jeśli jest wymagane */} {require_salary && (

{min_salary} - {max_salary} PLN

@@ -24,4 +25,19 @@ const ListingSmall = ({ id, name, company_name, min_salary, max_salary, require_ ); }; -export default ListingSmall; \ No newline at end of file +export default ListingSmall; + +ListingSmall.propTypes = { + id: propTypes.number, + name: propTypes.string, + company_name: propTypes.string, + min_salary: propTypes.number, + max_salary: propTypes.number, + require_salary: propTypes.bool, + index: propTypes.number, + onClick: propTypes.func, + _class: propTypes.string, + image: propTypes.string, + selected: propTypes.bool, + blur: propTypes.string +} \ No newline at end of file diff --git a/src/components/Login.jsx b/src/components/Login.jsx index 8f0a335..c19e092 100644 --- a/src/components/Login.jsx +++ b/src/components/Login.jsx @@ -1,4 +1,4 @@ -import React from 'react' +import propTypes from 'prop-types'; import styles from '../style'; const Login = ({isOpen, onClose}) => { @@ -31,4 +31,9 @@ const Login = ({isOpen, onClose}) => { ) } +Login.propTypes = { + isOpen: propTypes.bool, + onClose: propTypes.func +} + export default Login diff --git a/src/components/Mininav.jsx b/src/components/Mininav.jsx index c5d5593..5ae1c5e 100644 --- a/src/components/Mininav.jsx +++ b/src/components/Mininav.jsx @@ -1,8 +1,7 @@ -import React, { useState } from 'react' +import { useState } from 'react' import Register from './Register'; import Login from './Login'; -import { BrowserRouter as Router } from "react-router-dom"; -import { Route, Routes } from "react-router-dom"; + const Mininav = () => { const [isPopupOpen, setPopupOpen] = useState(false) @@ -17,7 +16,7 @@ const Mininav = () => { <>
{/* Link otwierający modal */} - Panel pracodawcy + {/* Panel pracodawcy */} diff --git a/src/components/NavBar.jsx b/src/components/NavBar.jsx index 9d94ae7..8d12194 100644 --- a/src/components/NavBar.jsx +++ b/src/components/NavBar.jsx @@ -1,10 +1,10 @@ -import React from 'react' import { linki, linki_home } from '../consts'; import { close, search, menu, IzaacLOGO} from '../assets'; import { useState } from 'react'; import { useLocation } from 'react-router-dom'; import { Link } from 'react-router-dom'; import Mininav from './Mininav'; + const NavBar = () => { const[toggle, setToggle] = useState(false) const[toggleSearch, setToggleSearch] = useState(false) @@ -20,7 +20,7 @@ const NavBar = () => { const currentLinks = getLinks() return ( -
) } - +Register.propTypes = { + isOpen: propTypes.bool, + onClose: propTypes.func +} export default Register diff --git a/src/components/Salary.jsx b/src/components/Salary.jsx index 762ea0f..de97710 100644 --- a/src/components/Salary.jsx +++ b/src/components/Salary.jsx @@ -1,5 +1,5 @@ -import React, { useState, useEffect } from 'react' -import styles from '../style' +import { useState, useEffect } from 'react' +import propTypes from 'prop-types' import {employment_types, work_from_home } from '../consts' @@ -112,5 +112,18 @@ const Salary = ({handleChange, formData, removeFields, setFormData}) => {
) } +Salary.propTypes = { + handleChange: propTypes.func, + formData: propTypes.object, + removeFields: propTypes.func, + setFormData: propTypes.func, + min_salary: propTypes.string, + max_salary: propTypes.string, + require_salary: propTypes.bool, + employment_type: propTypes.string, + work_from_home: propTypes.string + +} export default Salary + diff --git a/src/components/Search.jsx b/src/components/Search.jsx index 15cae22..76282aa 100644 --- a/src/components/Search.jsx +++ b/src/components/Search.jsx @@ -1,19 +1,61 @@ -import React from 'react' + +import { useEffect, useState } from 'react' +import propTypes from 'prop-types' const Search = (props) => { - return ( -
-
); }; +SkillsList.propTypes = { + skillData: propTypes.array, + skill_names: propTypes.array, +}; export default SkillsList; diff --git a/src/components/SkillRender.jsx b/src/components/SkillRender.jsx index 33d1aa1..df6dcd7 100644 --- a/src/components/SkillRender.jsx +++ b/src/components/SkillRender.jsx @@ -1,5 +1,4 @@ -import React from 'react' - +import propTypes from 'prop-types'; const levelMappings = { 'N': 'Nice to have', @@ -42,4 +41,10 @@ const SkillRender = ({key, skill, level,}) => { ) }; +SkillRender.propTypes = { + key: propTypes.number, + skill: propTypes.string, + level: propTypes.string, +}; + export default SkillRender; \ No newline at end of file diff --git a/src/components/SkillsSelector.jsx b/src/components/SkillsSelector.jsx index ce91a39..cbcbe9b 100644 --- a/src/components/SkillsSelector.jsx +++ b/src/components/SkillsSelector.jsx @@ -1,6 +1,6 @@ -import React, { useState, useEffect } from 'react'; +import { useState, useEffect } from 'react'; +import propTypes from 'prop-types'; import SelectedSkill from './SelectedSkill'; -import axios from 'axios'; const SkillsSelector = ({ formData, setFormData, skills }) => { const [inputValue, setInputValue] = useState(''); @@ -101,4 +101,10 @@ const SkillsSelector = ({ formData, setFormData, skills }) => { ); }; +SkillsSelector.propTypes = { + formData: propTypes.object.isRequired, + setFormData: propTypes.func.isRequired, + skills: propTypes.array.isRequired +}; + export default SkillsSelector; diff --git a/src/components/StepFourJoblisting.jsx b/src/components/StepFourJoblisting.jsx index 9e87d33..9dde322 100644 --- a/src/components/StepFourJoblisting.jsx +++ b/src/components/StepFourJoblisting.jsx @@ -1,6 +1,9 @@ -import React from "react"; +import propTypes from "prop-types"; + import styles from "../style"; import TextDivider from "./TextDivider"; + + const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => { return (
@@ -120,4 +123,11 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => { ); }; +StepFourJoblisting.propTypes = { + handleChange: propTypes.func, + formData: propTypes.object, + nextStep: propTypes.func, + prevStep: propTypes.func, +}; + export default StepFourJoblisting; diff --git a/src/components/StepOneJoblisting.jsx b/src/components/StepOneJoblisting.jsx index a2fd41e..213a6ef 100644 --- a/src/components/StepOneJoblisting.jsx +++ b/src/components/StepOneJoblisting.jsx @@ -1,5 +1,7 @@ -import React from "react"; + import styles from "../style"; +import propTypes from "prop-types"; + const StepOneJoblisting = ({ nextStep, handleChange, formData }) => { // Funkcja do obsługi kliknięcia na div i aktualizacji stanu const handleDivClick = (value) => () => { @@ -76,4 +78,10 @@ const StepOneJoblisting = ({ nextStep, handleChange, formData }) => { ); }; +StepOneJoblisting.propTypes = { + nextStep: propTypes.func, + handleChange: propTypes.func, + formData: propTypes.object, +}; + export default StepOneJoblisting; diff --git a/src/components/StepThreeJoblisting.jsx b/src/components/StepThreeJoblisting.jsx index 35a3653..defa578 100644 --- a/src/components/StepThreeJoblisting.jsx +++ b/src/components/StepThreeJoblisting.jsx @@ -1,12 +1,13 @@ -import React, { useEffect } from 'react'; + import DOMPurify from 'dompurify'; -import styles from '../style'; import TextDivider from './TextDivider'; import ListingSmall from './ListingSmall'; import { IzaacLOGO } from '../assets' import SkillsList from './SkillList'; +import PropTypes from 'prop-types'; + const StepThreeJoblisting = ({ formData, prevStep, skills, handleSubmit }) => { // Funkcja do przetwarzania HTML i dodawania klas const processHTML = (htmlString) => { @@ -103,4 +104,11 @@ const StepThreeJoblisting = ({ formData, prevStep, skills, handleSubmit }) => { ); } +StepThreeJoblisting.propTypes = { + formData: PropTypes.object, + prevStep: PropTypes.func, + skills: PropTypes.array, + handleSubmit: PropTypes.func +} + export default StepThreeJoblisting; diff --git a/src/components/StepTwoJoblisting.jsx b/src/components/StepTwoJoblisting.jsx index 09028dd..c462bae 100644 --- a/src/components/StepTwoJoblisting.jsx +++ b/src/components/StepTwoJoblisting.jsx @@ -1,4 +1,7 @@ -import React, { useState } from 'react' +import { useState } from 'react' +import propTypes from 'prop-types'; + +import { categories, experience_levels } from '../consts'; import styles from '../style' import { CKEditor } from '@ckeditor/ckeditor5-react'; import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; @@ -7,8 +10,6 @@ import SkillsSelector from './SkillsSelector'; import Salary from './Salary'; import { placeholderImage } from '../assets'; -import { categories, experience_levels } from '../consts'; - const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setFormData, removeFields, skills }) => { const [editorData, setEditorData] = useState(''); const [imageSrc, setImageSrc] = useState(placeholderImage); @@ -230,4 +231,14 @@ const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setForm ) } +StepTwoJoblisting.propTypes = { + nextStep: propTypes.func, + prevStep: propTypes.func, + handleChange: propTypes.func, + formData: propTypes.object, + setFormData: propTypes.func, + removeFields: propTypes.func, + skills: propTypes.array +} + export default StepTwoJoblisting diff --git a/src/components/Success.jsx b/src/components/Success.jsx index 9de475b..a6c76c0 100644 --- a/src/components/Success.jsx +++ b/src/components/Success.jsx @@ -1,4 +1,4 @@ -import React from 'react' + import TextDivider from './TextDivider' const Success = () => { diff --git a/src/components/TextDivider.jsx b/src/components/TextDivider.jsx index e1a9f94..292a4a7 100644 --- a/src/components/TextDivider.jsx +++ b/src/components/TextDivider.jsx @@ -1,6 +1,7 @@ -import React from 'react' -const TextDivider = ({text }) => { +import propTypes from 'prop-types' + +const TextDivider = ({ text }) => { return (
@@ -13,4 +14,7 @@ const TextDivider = ({text }) => { ) } +TextDivider.propTypes = { + text: propTypes.string +} export default TextDivider diff --git a/src/components/WorkApp.jsx b/src/components/WorkApp.jsx index 24ce4b6..f0e3b3f 100644 --- a/src/components/WorkApp.jsx +++ b/src/components/WorkApp.jsx @@ -2,13 +2,15 @@ import React from "react"; import { useState, useEffect } from "react"; import ListingSmall from "./ListingSmall"; -import SkillRender from "./SkillRender"; -import Search from "./Search"; +// import SkillRender from "./SkillRender"; +// import Search from "./Search"; import Filter from "./Filter"; -import Category from "./Category"; +// import Category from "./Category"; import JobOfferContent from "./JobOfferContent"; import { categories } from "../consts"; import axios from "axios"; +import { Link, useParams } from "react-router-dom"; + function renderCircles(level) { let numberOfFilledCircles; @@ -44,11 +46,17 @@ function renderCircles(level) { } const WorkApp = () => { + let { id } = useParams(); + const [isDetailsVisible, setIsDetailsVisible] = useState(false); // Czy szczegóły są widoczne const [isOpen, setIsOpen] = useState(false); - // Funkcja pobierająca dane z API + // useEffect(() => { + // if (!isOpen) { + // setSearchQuery({ name: "", localization: "", min_salary: "", max_salary: "" }); + // }}, [isOpen]); + const [ogloszenia, setOgloszenia] = useState([]); const [skills, setSkills] = useState([]); @@ -64,12 +72,15 @@ const WorkApp = () => { // console.log(data); if (data.length > 0) { setSelectedOgloszenie(data[0]); - // console.log(data[0]) + console.log(data[0]) } } catch (error) { console.error(error); } }; + if (id === undefined) { + id = ogloszenia[0]?.id; + } const getSkills = async () => { try { @@ -86,26 +97,27 @@ const WorkApp = () => { const [searchQuery, setSearchQuery] = useState({}); + const clearSearchQuery = () => { + setSearchQuery({}); + }; + const [selectedOgloszenie, setSelectedOgloszenie] = useState(ogloszenia[0]); useEffect(() => { getOgloszenia(); getSkills(); + }, []); + useEffect(() => { + document.title = `Izaac - ${selectedOgloszenie?.name}`; + }, [selectedOgloszenie?.name]); + const handleOgloszenieClick = (ogloszenie) => { setSelectedOgloszenie(ogloszenie); setIsDetailsVisible(true); // Pokaż szczegóły na urządzeniach mobilnych }; - const prevSlide = () => { - setCurrentSlide( - (prevSlide) => (prevSlide - 1 + categories.length) % categories.length - ); - }; - const nextSlide = () => { - setCurrentSlide((prevSlide) => (prevSlide + 1) % categories.length); - }; - const [currentSlide, setCurrentSlide] = React.useState(0); + // Funkcja do powrotu do listy ogłoszeń const handleBackToList = () => { setIsDetailsVisible(false); @@ -125,53 +137,50 @@ const WorkApp = () => { }, []); return ( -
-
-
- - {categories.map((category, index) => ( -
- { getOgloszenia({ category: category.id }); }} - /> -
- ))} - -
+
+
+
-
-

+
+
+

Oferty pracy

+
-
- {isOpen && } +
+ {getOgloszenia(searchQuery) + setIsOpen(!isOpen) + }}/>
+
+
{ogloszenia.map((ogloszenie, index) => ( + { require_salary={ogloszenie.require_salary} image={ogloszenie.image} index={index} - onClick={() => handleOgloszenieClick(ogloszenie)} + onClick={() => {handleOgloszenieClick(ogloszenie)}} + selected={selectedOgloszenie?.id === ogloszenie.id} + blur={isOpen ? 'blur' : ''} /> + ))} +
{isDetailsVisible && (
@@ -202,19 +215,8 @@ const WorkApp = () => { )} {selectedOgloszenie && ( - + )} - {/*
- {Object.entries(selectedOgloszenie.neededSkills).map(([skill, level]) => ( - - ))} -
-
- {selectedOgloszenie.tresc} -
*/}

diff --git a/src/consts/index.js b/src/consts/index.js index 314d91f..079ff4f 100644 --- a/src/consts/index.js +++ b/src/consts/index.js @@ -169,12 +169,12 @@ export const linki = [ }, { "id": "2", - "name": "work/postings", + "name": "work/joboffers", "title": "Ogłoszenia", }, { "id": "3", - "name": "work/jobposting", + "name": "work/addjoboffer", "title": "Dodaj ogłoszenie", }, { diff --git a/src/index.css b/src/index.css index f9d7ff6..96f809a 100644 --- a/src/index.css +++ b/src/index.css @@ -22,6 +22,27 @@ } } +/* @layer components { + .no-spin-buttons::-webkit-inner-spin-button, + .no-spin-buttons::-webkit-outer-spin-button { + @apply -webkit-appearance-none margin-0; + } + .no-spin-buttons { + @apply -moz-appearance-textfield; + } +} */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +/* Dla Firefox */ +input[type="number"] { + -moz-appearance: textfield; +} + @tailwind components; @tailwind utilities; @@ -60,11 +81,43 @@ } /* Expanded state styles */ -.expanded { - max-height: fit-content; /* Adjust as needed */ - opacity: 1; +.collapsible { + max-height: 0; + overflow: hidden; + transition-property: all; + transition-timing-function: ease-in-out; + transition-duration: 0.5s; } +/* Styl dla elementu, gdy jest rozwinięty */ +.collapsible.expanded { + max-height: 1000px; /* Przykładowa maksymalna wysokość, może wymagać dostosowania */ + opacity: 1; + transition-property: all; + transition-timing-function: ease-in-out; + transition-duration: 0.5s; +} + +.div-transition { + transition-property: filter; + transition-duration: 1s; + transition-timing-function: ease-in-out; +} + + +.noblur { + filter: blur(0px); + transition-property: filter; + transition-duration: 0.5s; + transition-timing-function: ease-in-out; +} + +.blur { + filter: blur(5px); + transition-property: filter; + transition-duration: 0.5s; + transition-timing-function: ease-in-out; +} .minus-z-index { z-index: -10; } @@ -109,59 +162,4 @@ .sidebar-hide { -webkit-animation: slide-down 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both; animation: slide-down 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both; -} - -@-webkit-keyframes slide-top { - 0% { - -webkit-transform: translateX(600px); - transform: translateX(600px); - } - 100% { - -webkit-transform: translateX(0); - transform: translateX(0); - } -} - -@keyframes slide-top { - 0% { - -webkit-transform: translateX(600px); - transform: translateX(600px); - } - 100% { - -webkit-transform: translateX(0); - transform: translateX(0); - } -} - -@-webkit-keyframes slide-down { - 0% { - -webkit-transform: translateX(0); - transform: translateX(0); - } - 100% { - -webkit-transform: translateX(600px); - transform: translateX(600px); - } -} - -@keyframes slide-down { - 0% { - -webkit-transform: translateX(0); - transform: translateX(0); - } - 100% { - -webkit-transform: translateX(600px); - transform: translateX(600px); - } -} - - -@media (max-width: 768px) { - .details-section { - display: none; - } - .list-section { - display: block; - } -} - +} \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index 0d1d585..aca5157 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -7,7 +7,7 @@ module.exports = { colors: { primary: "#00040f", secondary: "#00f6ff", - dimWhite: "rgba(255, 255, 255, 0.7)", + dimWhite: "rgba(255, 255, 255, 0.8)", dimBlue: "rgba(9, 151, 124, 0.1)", }, fontFamily: { From 97b7e8726d7b3446c55faa82137de0a1cac1106e Mon Sep 17 00:00:00 2001 From: Jakub Kaniecki Date: Tue, 9 Jul 2024 22:37:54 +0200 Subject: [PATCH 6/7] filtry + ciastko --- package-lock.json | 6 +-- package.json | 2 +- src/App.jsx | 8 ++-- src/components/Cookies.jsx | 29 ++++++++++++++ src/components/Filter.jsx | 75 ++++++++++--------------------------- src/components/NavBar.jsx | 6 +-- src/components/Selector.jsx | 4 +- src/components/WorkApp.jsx | 8 ++-- 8 files changed, 65 insertions(+), 73 deletions(-) create mode 100644 src/components/Cookies.jsx diff --git a/package-lock.json b/package-lock.json index e34d81d..4afe8c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1880,9 +1880,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001620", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz", - "integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==", + "version": "1.0.30001640", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz", + "integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==", "dev": true, "funding": [ { diff --git a/package.json b/package.json index 850d1ca..de1f53a 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "vite", "build": "vite build", - "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", + "lint": "eslint -c eslint.config.js --ext .js,.jsx,.ts,.tsx .", "preview": "vite preview" }, "dependencies": { diff --git a/src/App.jsx b/src/App.jsx index 1be36b2..0265ae1 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -7,20 +7,21 @@ import { Route, Routes } from "react-router-dom"; import Contact from "./components/Contact"; import Mininav from "./components/Mininav"; import AddJobListing from "./components/AddJobListing"; +import Cookies from "./components/Cookies"; function App() { return (
-
+
{/* */} -
+
-
+
} /> @@ -32,6 +33,7 @@ function App() { {/* } /> */} {/* Add more routes as needed */} +
diff --git a/src/components/Cookies.jsx b/src/components/Cookies.jsx new file mode 100644 index 0000000..f8de240 --- /dev/null +++ b/src/components/Cookies.jsx @@ -0,0 +1,29 @@ +import propTypes from 'prop-types' +import { useState } from 'react' +const Cookies = props => { + const handleCookies = () => { + localStorage.setItem('cookies', true) + } + const cookies = localStorage.getItem('cookies') + // if(cookies) return null + const [show, setShow] = useState(true) + if (cookies) return null; + if (!show) return null; + return ( + <> +
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+ + +
+ + ) +} + +Cookies.propTypes = { + +} + +export default Cookies \ No newline at end of file diff --git a/src/components/Filter.jsx b/src/components/Filter.jsx index 0a4dd71..b92e93f 100644 --- a/src/components/Filter.jsx +++ b/src/components/Filter.jsx @@ -7,64 +7,19 @@ import Selector from './Selector'; const Filter = (props) => { useEffect(() => { console.log(props.searchQuery) - console.log(selectedCategories) - console.log(selectedWorkFromHome) - console.log(selectedEmploymentTypes) - console.log(valueminSalary) }, [props.searchQuery]); - const [selectedCategories, setSelectedCategories] = useState([]); - const [selectedWorkFromHome, setSelectedWorkFromHome] = useState([]); - const [selectedEmploymentTypes, setSelectedEmploymentTypes] = useState([]); - const [valueminSalary, setValueminSalary] = useState(''); - const [valuemaxSalary, setValuemaxSalary] = useState(''); - const [valueName, setValueName] = useState(''); - const [valueLocalization, setValueLocalization] = useState(''); - - useEffect(() => { - setSelectedCategories([]) - setSelectedWorkFromHome([]) - setSelectedEmploymentTypes([]) - setValueminSalary('') - setValuemaxSalary('') - setValueName('') - setValueLocalization('') - }, [props.clearSearchQuery]) const handle_checked_change = (e) => { - switch (e.target.name) { - case 'categories': - if (e.target.checked) { - setSelectedCategories([...selectedCategories, e.target.value]); - } else { - setSelectedCategories(selectedCategories.filter(category => category !== e.target.value)); - } - props.setSearchQuery(prevState => - ({...prevState, - categories: e.target.checked ? [...(prevState.categories || []), e.target.value] : (prevState.categories || []).filter(category => category !== e.target.value)})); - break; - case 'work_from_home': - if (e.target.checked) { - setSelectedWorkFromHome([...selectedWorkFromHome, e.target.value]); - } else { - setSelectedWorkFromHome(selectedCategories.filter(work_from_home => work_from_home !== e.target.value)); - } - props.setSearchQuery(prevState => - ({...prevState, - work_from_home: e.target.checked ? [...(prevState.work_from_home || []), e.target.value] : (prevState.work_from_home || []).filter(work_from_home => work_from_home !== e.target.value)})); - break; - case 'employment': - if (e.target.checked) { - setSelectedEmploymentTypes([...selectedEmploymentTypes, e.target.value]); - } else { - setSelectedEmploymentTypes(selectedCategories.filter(employment => employment !== e.target.value)); - } - props.setSearchQuery(prevState => - ({...prevState, - employment: e.target.checked ? [...(prevState.employment || []), e.target.value] : (prevState.employment || []).filter(employment => employment !== e.target.value)})); - break; - } + const { name, value, checked } = e.target; + props.setSearchQuery(prevState => { + const newArray = checked + ? [...(prevState[name] || []), value] + : (prevState[name] || []).filter(item => item !== value); + return { ...prevState, [name]: newArray }; + }); } + return ( @@ -103,9 +58,9 @@ const Filter = (props) => { setSearchQuery={props.setSearchQuery} _type='text' value={props.searchQuery.max_salary || ''}/> - - - + + +
diff --git a/src/components/WorkApp.jsx b/src/components/WorkApp.jsx index f0e3b3f..395994b 100644 --- a/src/components/WorkApp.jsx +++ b/src/components/WorkApp.jsx @@ -137,12 +137,12 @@ const WorkApp = () => { }, []); return ( -
-
+
+
{
From 45a2c8252e17800481d4ab33d607f64b372b6a57 Mon Sep 17 00:00:00 2001 From: Jakub Kaniecki Date: Sat, 27 Jul 2024 01:42:21 +0200 Subject: [PATCH 7/7] zmiany do mobile, filtrowanie, poprawki --- src/App.jsx | 2 +- src/components/CategorySelect.jsx | 106 ++++++++++++ src/components/Cookies.jsx | 8 +- src/components/Filter.jsx | 236 ++++++++++++++++++-------- src/components/RangeSlider.jsx | 76 +++++++++ src/components/Salary.jsx | 4 +- src/components/Search.jsx | 15 +- src/components/Selector.jsx | 44 ++--- src/components/StepFourJoblisting.jsx | 6 +- src/components/StepOneJoblisting.jsx | 60 ++++--- src/components/StepTwoJoblisting.jsx | 20 ++- src/components/WorkApp.jsx | 22 ++- src/consts/index.js | 31 ++++ src/index.css | 150 +++++++++++++++- 14 files changed, 639 insertions(+), 141 deletions(-) create mode 100644 src/components/CategorySelect.jsx create mode 100644 src/components/RangeSlider.jsx diff --git a/src/App.jsx b/src/App.jsx index 0265ae1..6f27804 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -21,7 +21,7 @@ function App() {
-
+
} /> diff --git a/src/components/CategorySelect.jsx b/src/components/CategorySelect.jsx new file mode 100644 index 0000000..886f1d3 --- /dev/null +++ b/src/components/CategorySelect.jsx @@ -0,0 +1,106 @@ +import { useEffect, useState } from 'react'; +import PropTypes from 'prop-types'; +import { categories } from '../consts'; +import { search } from '../assets'; + +const CategorySelect = props => { + const [inputValue, setInputValue] = useState(''); + const [suggestions, setSuggestions] = useState([]); + const [selectedCategoryIds, setSelectedCategoryIds] = useState([]); + + useEffect(() => { + console.log(suggestions); + console.log(selectedCategoryIds); + }, [suggestions, selectedCategoryIds]); + + useEffect(() => { + if (props.searchQuery && props.searchQuery.categories) { + setSelectedCategoryIds(props.searchQuery.categories); + } + }, [props.searchQuery]); + + // useEffect(() =>{ + // setSelectedCategoryIds([]) + // }, [props.clearSearchQuery]) + + const handleInputChange = (e) => { + const value = e.target.value; + setInputValue(value); + if (value.length > 0) { + setSuggestions(categories.filter(category => + category.name.toLowerCase().includes(value.toLowerCase()) && + !selectedCategoryIds.includes(category.id) + )); + } else { + setSuggestions([]); + } + } + + const handleSuggestionClick = (suggestion) => { + if (!selectedCategoryIds.includes(suggestion.id)) { + const newSelectedIds = [...selectedCategoryIds, suggestion.id]; + setSelectedCategoryIds(newSelectedIds); + props.setSearchQuery(prevState => ({...prevState, categories: newSelectedIds })); + } + setInputValue(''); + setSuggestions([]); + } + + const handleRemoveCategory = (id) => { + const newSelectedIds = selectedCategoryIds.filter(prevId => prevId !== id); + setSelectedCategoryIds(newSelectedIds); + props.setSearchQuery({ categories: newSelectedIds }); + } + + return ( +
+

Kategorie

+
+ {selectedCategoryIds.map(id => { + const category = categories.find(cat => cat.id === id); + return ( +
handleRemoveCategory(id)} + className='min-w-fit w-8 py-1 px-2 mr-3 border-2 hover:bg-gray-300 rounded-xl hover:cursor-pointer ' + > +

{category.name} + × +

+
+ ); + })} +
+ + {inputValue.length >= 1 && suggestions.length > 0 && ( +
+ {suggestions.map(suggestion => ( +
handleSuggestionClick(suggestion)} + > + {suggestion.name} +
+ ))} +
+ )} +
+ ) +} + +CategorySelect.propTypes = { + setSearchQuery: PropTypes.func.isRequired, + searchQuery: PropTypes.shape({ + categories: PropTypes.arrayOf(PropTypes.string) + }) + +} + +export default CategorySelect \ No newline at end of file diff --git a/src/components/Cookies.jsx b/src/components/Cookies.jsx index f8de240..ddcdc57 100644 --- a/src/components/Cookies.jsx +++ b/src/components/Cookies.jsx @@ -11,11 +11,11 @@ const Cookies = props => { if (!show) return null; return ( <> -
-

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

- + Wyrażenie zgody
diff --git a/src/components/Filter.jsx b/src/components/Filter.jsx index b92e93f..33fc1dd 100644 --- a/src/components/Filter.jsx +++ b/src/components/Filter.jsx @@ -1,91 +1,185 @@ - -import Search from './Search' -import { useEffect, useState } from 'react'; -import { categories, work_from_home, employment_types } from '../consts'; -import propTypes from 'prop-types'; +import { useCallback, useEffect, useMemo } from 'react'; +import PropTypes from 'prop-types'; +import Search from './Search'; import Selector from './Selector'; -const Filter = (props) => { - useEffect(() => { - console.log(props.searchQuery) - }, [props.searchQuery]); +import RangeSlider from './RangeSlider'; +import CategorySelect from './CategorySelect'; +import { categories, work_from_home, employment_types } from '../consts'; + +const Filter = ({ isOpen, searchQuery, setSearchQuery, clearSearchQuery, onClick }) => { + const [min_salary, max_salary] = [0, 100000]; + + useEffect(() => { + console.log(searchQuery); + }, [searchQuery]); - const handle_checked_change = (e) => { - const { name, value, checked } = e.target; - props.setSearchQuery(prevState => { - const newArray = checked - ? [...(prevState[name] || []), value] - : (prevState[name] || []).filter(item => item !== value); - return { ...prevState, [name]: newArray }; - }); - } - + const handleRangeChange = useCallback((newMin, newMax) => { + setSearchQuery(prevState => ({ + ...prevState, + min_salary: newMin, + max_salary: newMax + })); + }, [setSearchQuery]); + const handleChange = useCallback((e, name) => { + const value = e.target.value; + const numValue = parseInt(value, 10); + + setSearchQuery(prevState => { + switch (name) { + case 'name': + return { ...prevState, name: value }; + case 'min_salary': + if (value === '' || isNaN(numValue)) { + return { ...prevState, min_salary: '' }; + } + return { ...prevState, min_salary: numValue }; + case 'max_salary': + if (value === '' || isNaN(numValue)) { + return { ...prevState, max_salary: '' }; + } + return { ...prevState, max_salary: numValue }; + default: + return prevState; + } + }); + }, [setSearchQuery]); + + const handleCheckedChange = useCallback((e) => { + const { name, value, checked } = e.target; + setSearchQuery(prevState => { + // Sprawdź, czy dla danej nazwy już istnieje tablica w stanie + if (!prevState[name]) { + prevState[name] = []; + } + + if (checked) { + // Jeśli checkbox jest zaznaczony, dodaj wartość do odpowiedniej tablicy + return { + ...prevState, + [name]: [...prevState[name], value] + }; + } else { + // Jeśli checkbox jest odznaczony, usuń wartość z odpowiedniej tablicy + return { + ...prevState, + [name]: prevState[name].filter(item => item !== value) + }; + } + }); + }, [setSearchQuery]); + + const filterButtonClass = useMemo(() => ( + 'bg-gray-600 text-white py-1 sm:py-3 px-12 mx-auto sm:mx-40 col-span-2 rounded-md font-semibold ' + + 'text-xl hover:bg-gray-500 duration-300 hover:scale-110 my-3 sm:my-5 sm:min-h-full' + ), []); return ( - // idea - make the page whole page grayed out and only the filter is visible -
-
-
-

Filtry

- - +
+ + handleChange(e, 'name')} + /> + +
+ handleChange(e, 'min_salary')} + /> + handleChange(e, 'max_salary')} + /> + +
+ + {/* */} + {/* + */} + +
- - - - - - - - - - -
- ) + ); }; Filter.propTypes = { - isOpen: propTypes.bool, - searchQuery: propTypes.object, - setSearchQuery: propTypes.func, - categories: propTypes.array, - clearSearchQuery: propTypes.func, - onClick: propTypes.func + isOpen: PropTypes.bool.isRequired, + searchQuery: PropTypes.shape({ + name: PropTypes.string, + min_salary: PropTypes.number, + max_salary: PropTypes.number, + categories: PropTypes.arrayOf(PropTypes.string), + work_from_home: PropTypes.arrayOf(PropTypes.string), + employment_types: PropTypes.arrayOf(PropTypes.string) + }), + setSearchQuery: PropTypes.func.isRequired, + clearSearchQuery: PropTypes.func.isRequired, + onClick: PropTypes.func.isRequired }; Filter.defaultProps = { searchQuery: { categories: [], work_from_home: [], - employment: [] + employment_types: [] } }; -export default Filter; +export default Filter; \ No newline at end of file diff --git a/src/components/RangeSlider.jsx b/src/components/RangeSlider.jsx new file mode 100644 index 0000000..2201fa4 --- /dev/null +++ b/src/components/RangeSlider.jsx @@ -0,0 +1,76 @@ +import { useRef, useEffect, useCallback } from 'react'; +import propTypes from 'prop-types'; + + +const RangeSlider = ({ min, max, minVal, maxVal, setSearchQuery, onRangeChange, isOpen }) => { + const minValRef = useRef(minVal); + const maxValRef = useRef(maxVal); + const range = useRef(null); + + const getPercent = useCallback( + (value) => Math.round(((value - min) / (max - min)) * 100), + [min, max] + ); + + useEffect(() => { + const minPercent = getPercent(minVal === '' ? min : minVal); + const maxPercent = getPercent(maxVal === '' ? max : maxVal); + + if (range.current) { + range.current.style.left = `${minPercent}%`; + range.current.style.width = `${maxPercent - minPercent}%`; + } + }, [minVal, maxVal, getPercent, min, max]); + + const handleChange = useCallback((event) => { + const { id, value } = event.target; + const numValue = Number(value); + + let newMinVal = minVal === '' ? min : minVal; + let newMaxVal = maxVal === '' ? max : maxVal; + + if (id === 'range1') { + newMinVal = numValue; + minValRef.current = newMinVal; + } else if (id === 'range2') { + newMaxVal = numValue; + maxValRef.current = newMaxVal; + } + + onRangeChange(newMinVal, newMaxVal); + }, [minVal, maxVal, min, max, onRangeChange]); + + return ( +
+ (maxVal === '' ? max - 100 : maxVal - 100) ? 5 : undefined, } : { display: 'none' }} + /> + + +
+
+
+
+
+ ); +}; + +export default RangeSlider; \ No newline at end of file diff --git a/src/components/Salary.jsx b/src/components/Salary.jsx index de97710..fe016c9 100644 --- a/src/components/Salary.jsx +++ b/src/components/Salary.jsx @@ -82,7 +82,7 @@ const Salary = ({handleChange, formData, removeFields, setFormData}) => { className={`h-12 border-2 rounded-xl px-5 mx-4 w-full ${!require_salary ? 'bg-slate-200' : ''} `}/>
-

Typ kontraktu

+

Typ
kontraktu

-

Praca zdalna

+

Praca
zdalna

- {value_to_map_from.name} - - ))} -
+ {props.name} + {props.value_to_map_from.map((value_to_map_from) => ( + + ))} +
) } Selector.propTypes = { - value_to_map_from: propTypes.array, - setSearchQuery: propTypes.func, - name: propTypes.string, - inputname: propTypes.string, - onChange: propTypes.func, - state: propTypes.array + value_to_map_from: PropTypes.array, + setSearchQuery: PropTypes.func, + name: PropTypes.string, + inputname: PropTypes.string, + onChange: PropTypes.func, + state: PropTypes.object } -export default Selector +export default Selector \ No newline at end of file diff --git a/src/components/StepFourJoblisting.jsx b/src/components/StepFourJoblisting.jsx index 9dde322..3980a4d 100644 --- a/src/components/StepFourJoblisting.jsx +++ b/src/components/StepFourJoblisting.jsx @@ -102,15 +102,15 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => { -
); diff --git a/src/components/StepTwoJoblisting.jsx b/src/components/StepTwoJoblisting.jsx index c462bae..ce47a7f 100644 --- a/src/components/StepTwoJoblisting.jsx +++ b/src/components/StepTwoJoblisting.jsx @@ -1,6 +1,6 @@ import { useState } from 'react' import propTypes from 'prop-types'; - +import MaximumLength from '@ckeditor/ckeditor5-react' import { categories, experience_levels } from '../consts'; import styles from '../style' import { CKEditor } from '@ckeditor/ckeditor5-react'; @@ -17,7 +17,7 @@ const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setForm const data = editor.getData(); setEditorData(data); } - + const max_char = 600; const handleNextStep = () => { if (validateForm()) { console.log(errors) @@ -137,6 +137,16 @@ const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setForm editor={ClassicEditor} data={formData['content'] || ''} required + // config={{ + // plugins: [WordCount], + // toolbar: ['wordCount'], + // wordCount: { + // onUpdate: stats => { + // console.log(stats.words, stats.characters) + // } + // } + + // }} onChange={(event, editor) => { const data = editor.getData(); handleChange('content')(data); // Wywołanie zmodyfikowanej funkcji handleChange @@ -205,11 +215,11 @@ const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setForm formData={formData}/>
-
+