Merge pull request 'IZCWRK-2' (#2) from develop into master
Some checks failed
continuous-integration/drone Build is failing

Reviewed-on: http://gitea.knck.pl/jakub.kaniecki/izaac-frontend/pulls/2
This commit is contained in:
jakub.kaniecki 2024-10-08 19:37:24 +00:00
commit 68d32a775f
8 changed files with 12567 additions and 30 deletions

12483
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@
"@ckeditor/ckeditor5-build-classic": "^40.0.0", "@ckeditor/ckeditor5-build-classic": "^40.0.0",
"@ckeditor/ckeditor5-build-multi-root": "^40.0.0", "@ckeditor/ckeditor5-build-multi-root": "^40.0.0",
"@ckeditor/ckeditor5-react": "^6.1.0", "@ckeditor/ckeditor5-react": "^6.1.0",
"@ckeditor/ckeditor5-word-count": "^43.2.0",
"axios": "^0.24.0", "axios": "^0.24.0",
"dompurify": "^3.0.6", "dompurify": "^3.0.6",
"react": "^18.2.0", "react": "^18.2.0",

17
src/components/Button.jsx Normal file
View File

@ -0,0 +1,17 @@
import React from 'react'
const Button = (props) => {
return (
<button
disabled={props.isDiasbled}
type="button"
onClick={props.nextStep}
className={`h-16 md:h-12 w-80 md:w-72 rounded-xl bg-gray-700 font-poppins font-semibold text-[14px] text-white hover:scale-125 duration-300 ${props.isDiasbled ? 'cursor-not-allowed hover:scale-100 duration-300' : ''}`}
>
{props.Text} &nbsp;&nbsp;
<span className="text-[18px]"></span>{" "}
</button>
)
}
export default Button

View File

@ -54,7 +54,7 @@ const CategorySelect = props => {
return ( return (
<div className='mb-3'> <div className='mb-3'>
<p className='text-center'>Kategorie</p> <p className='text-center'>Branża</p>
<div className='flex flex-wrap gap-y-2 mt-1 '> <div className='flex flex-wrap gap-y-2 mt-1 '>
{selectedCategoryIds.map(id => { {selectedCategoryIds.map(id => {
const category = categories.find(cat => cat.id === id); const category = categories.find(cat => cat.id === id);
@ -76,7 +76,7 @@ const CategorySelect = props => {
className='border-2 rounded-lg px-3 py-1 w-full mt-2' className='border-2 rounded-lg px-3 py-1 w-full mt-2'
value={inputValue} value={inputValue}
onChange={handleInputChange} onChange={handleInputChange}
placeholder='Wpisz kategorię...' placeholder='Wpisz branżę...'
/> />
{inputValue.length >= 1 && suggestions.length > 0 && ( {inputValue.length >= 1 && suggestions.length > 0 && (
<div className='absolute h-40 w-[90%] overflow-y-auto'> <div className='absolute h-40 w-[90%] overflow-y-auto'>

View File

@ -7,7 +7,7 @@ import CategorySelect from './CategorySelect';
import { categories, work_from_home, employment_types } from '../consts'; import { categories, work_from_home, employment_types } from '../consts';
const Filter = ({ isOpen, searchQuery, setSearchQuery, clearSearchQuery, onClick }) => { const Filter = ({ isOpen, searchQuery, setSearchQuery, clearSearchQuery, onClick }) => {
const [min_salary, max_salary] = [0, 100000]; const [min_salary, max_salary] = [0, 20000];
useEffect(() => { useEffect(() => {
console.log(searchQuery); console.log(searchQuery);

View File

@ -1,10 +1,30 @@
import propTypes from "prop-types"; import propTypes from "prop-types";
import { useEffect } from "react";
import styles from "../style"; import styles from "../style";
import TextDivider from "./TextDivider"; import TextDivider from "./TextDivider";
import Button from "./Button";
const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => { const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => {
const validateForm = () => {
const { first_name, last_name, contact_email, company_name, vat_number } = formData;
if (!first_name || !last_name || !contact_email || !company_name || !vat_number) {
return true;
};}
useEffect(() => {
validateForm();
}, [formData]);
const validateEmail = (e) => {
const email = e.target.value;
const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
if (!emailPattern.test(email)) {
alert("Niepoprawny adres e-mail");
}
}
return ( return (
<div className={`${styles.flexCenter}`}> <div className={`${styles.flexCenter}`}>
<div className="grid grid-cols-5"> <div className="grid grid-cols-5">
@ -57,6 +77,7 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => {
required required
id="contact_email" id="contact_email"
onChange={handleChange("contact_email")} onChange={handleChange("contact_email")}
onBlur={validateEmail}
placeholder="Adres mailowy..." placeholder="Adres mailowy..."
className={`px-4 mt-2 ${styles.paragraph}`} className={`px-4 mt-2 ${styles.paragraph}`}
/> />
@ -107,14 +128,11 @@ const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => {
<span className="text-[18px]"></span>&nbsp;&nbsp;Przejdź do <br className="block md:hidden"/> <span className="text-[18px]"></span>&nbsp;&nbsp;Przejdź do <br className="block md:hidden"/>
poprzedniego kroku poprzedniego kroku
</button> </button>
<button
type="button" <Button
onClick={nextStep} isDiasbled={validateForm()}
className="h-16 md:h-12 w-80 md:w-72 rounded-xl bg-gray-700 font-poppins font-semibold text-[14px] text-white hover:scale-125 duration-300" nextStep={nextStep}
> Text="Przejdź do następnego kroku"/>
Przejdź do następnego kroku &nbsp;&nbsp;
<span className="text-[18px]"></span>{" "}
</button>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
import { useState } from 'react' import { useEffect, useState } from 'react'
import propTypes from 'prop-types'; import propTypes from 'prop-types';
import MaximumLength from '@ckeditor/ckeditor5-react' import MaximumLength from '@ckeditor/ckeditor5-react'
import { categories, experience_levels } from '../consts'; import { categories, experience_levels } from '../consts';
@ -9,15 +9,31 @@ import ImageUpload from './ImageUpload';
import SkillsSelector from './SkillsSelector'; import SkillsSelector from './SkillsSelector';
import Salary from './Salary'; import Salary from './Salary';
import { placeholderImage } from '../assets'; import { placeholderImage } from '../assets';
import Button from './Button';
const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setFormData, removeFields, skills }) => { const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setFormData, removeFields, skills }) => {
const [editorData, setEditorData] = useState(''); const [editorData, setEditorData] = useState('');
const [imageSrc, setImageSrc] = useState(placeholderImage); const [imageSrc, setImageSrc] = useState(placeholderImage);
const handleEditorChange = (event, editor) => { const max_words = 500;
const data = editor.getData(); const countWords = (text) => {
setEditorData(data); return text.split(/\s/).filter(function(n) { return n != '' }).length;
} }
const max_char = 600;
const validateForm2 = () => {
const { name, company_name, localization, content, min_salary, max_salary, work_from_home, employment_type, image, skill_levels } = formData;
if (!name || !company_name || !localization || !content || !min_salary || !max_salary || !work_from_home || !employment_type || !image || !skill_levels) {
return true;
}
}
useEffect(() => {
if (formData.content) {
console.log(countWords(formData.content))
if (countWords(formData.content) > max_words) {
alert('Maksymalna liczba słów wynosi 500')
}
}
}, [formData.content])
const handleNextStep = () => { const handleNextStep = () => {
if (validateForm()) { if (validateForm()) {
console.log(errors) console.log(errors)
@ -30,7 +46,9 @@ const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setForm
const [errors, setErrors] = useState({}); const [errors, setErrors] = useState({});
const validateForm = () => { const validateForm = () => {
let newErrors = {}; let newErrors = {};
if (countWords(formData.content) > max_words) {
newErrors.content = 'Maksymalna liczba słów wynosi 600';
}
// Sprawdź każde wymagane pole // Sprawdź każde wymagane pole
if (!formData.name) { if (!formData.name) {
newErrors.name = 'To pole jest wymagane'; newErrors.name = 'To pole jest wymagane';
@ -188,6 +206,7 @@ const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setForm
<option key={index} value={category.id}>{category.name}</option> <option key={index} value={category.id}>{category.name}</option>
))} ))}
</select> </select>
<p className='font-poppins font-semibold text-slate-700 text-center text-[14px] mt-1 mb-2'>Poziom doświadczenia</p> <p className='font-poppins font-semibold text-slate-700 text-center text-[14px] mt-1 mb-2'>Poziom doświadczenia</p>
<select <select
value={formData['experience_level'] || 'default' } value={formData['experience_level'] || 'default' }
@ -224,15 +243,13 @@ const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setForm
text-white hover:scale-125 duration-300'> text-white hover:scale-125 duration-300'>
<span className='text-[18px]'></span>&nbsp;&nbsp; <span className='text-[18px]'></span>&nbsp;&nbsp;
Przejdź do poprzedniego kroku</button> Przejdź do poprzedniego kroku</button>
<button
type="button" <Button
onClick={handleNextStep} isDiasbled={validateForm2()}
className='h-16 md:h-12 w-80 md:w-72 rounded-xl nextStep={handleNextStep}
bg-gray-700 font-poppins Text="Przejdź do następnego kroku"/>
font-semibold text-[14px] scale-100
text-white hover:scale-125 duration-300'>
Przejdź do następnego kroku &nbsp;&nbsp;
<span className='text-[18px]'></span> </button>
</div> </div>
</form> </form>
</div> </div>
@ -251,4 +268,4 @@ StepTwoJoblisting.propTypes = {
skills: propTypes.array skills: propTypes.array
} }
export default StepTwoJoblisting export default StepTwoJoblisting

View File

@ -110,6 +110,7 @@ const WorkApp = () => {
name: '' name: ''
}); });
getSkills(); getSkills();
getOgloszenia()
setIsOpen(!isOpen) setIsOpen(!isOpen)
}; };