handleCircleClick(index)}
+ className={`justify-self-center w-3.5 h-3.5 rounded-full ${index < numberOfFilledCircles ? 'bg-red-300 hover:bg-red-700' : 'bg-gray-500 hover:bg-gray-600'}`}
+ />
+ ))}
+ >
+ );
+};
+
+
+const SelectedSkill = ({ skill, level, onLevelChange, removeSkillFromList, formData }) => {
+ const levelss = 'Nice to have';
+ const handleCircleClick = (levelIndex) => {
+ const level = levels[levelIndex];
+ onLevelChange(skill, level);
+ };
+ return (
+
+
+
{skill}
+
+
+
+ {renderCircles(level, handleCircleClick)}
+
+
{level}
+
+
+
+ );
+};
+
+export default SelectedSkill;
diff --git a/src/components/SkillsSelector.jsx b/src/components/SkillsSelector.jsx
new file mode 100644
index 0000000..3f78052
--- /dev/null
+++ b/src/components/SkillsSelector.jsx
@@ -0,0 +1,143 @@
+import React, { useState, useEffect } from 'react';
+import SelectedSkill from './SelectedSkill';
+const initialSkillsList = [
+ 'Inżynieria oprogramowania',
+ 'Analiza danych',
+ 'Projektowanie CAD',
+ 'Automatyka',
+ 'Robotyka',
+ 'Inżynieria materiałowa',
+ 'Inżynieria elektryczna',
+ 'Inżynieria mechaniczna',
+ 'Programowanie mikrokontrolerów',
+ 'Analiza strukturalna',
+ 'Modelowanie 3D',
+ 'Projektowanie układów elektronicznych',
+ 'Programowanie PLC',
+ 'Sztuczna inteligencja',
+ 'Machine learning',
+ 'Inżynieria chemiczna',
+ 'Inżynieria biomedyczna',
+ 'Inżynieria środowiska',
+ 'Automatyka przemysłowa',
+ 'Zarządzanie projektami technicznymi',
+ 'Prototypowanie',
+ 'Przetwarzanie sygnałów',
+ 'Inżynieria systemów',
+ 'Analiza termodynamiczna',
+ 'Fizyka stosowana',
+ 'Inżynieria procesowa',
+ 'Wytwarzanie addytywne',
+ 'Technologia nanomateriałów',
+ 'Projektowanie systemów wbudowanych',
+ 'Inżynieria bezpieczeństwa',
+ // ... więcej umiejętności ...
+];
+
+const SkillsSelector = ({formData, setFormData}) => {
+ const [inputValue, setInputValue] = useState('');
+ const [suggestions, setSuggestions] = useState([]);
+ const [selectedSkills, setSelectedSkills] = useState([]);
+
+ const handleInputChange = (e) => {
+ const value = e.target.value;
+ setInputValue(value);
+ if (value.length >= 0) {
+ setSuggestions(initialSkillsList.filter(skill =>
+ skill.toLowerCase().includes(value.toLowerCase())));
+ } else {
+ setSuggestions([]);
+ }
+ };
+
+ const handleSuggestionClick = (skill) => {
+ if (!selectedSkills.includes(skill)) {
+ setSelectedSkills(prevSkills => [skill, ...prevSkills]);
+ };
+ setSkillLevels(prevLevels => ({
+ ...prevLevels,
+ [skill]: 'Nice to have' // lub inny domyślny poziom
+ }));
+ setInputValue('');
+ setSuggestions([]);
+ };
+ const removeSkillFromList = (skillToRemove) => {
+ setSelectedSkills(prevSkills => prevSkills.filter(skill => skill !== skillToRemove));
+
+ setSkillLevels(prevLevels => {
+ const newLevels = { ...prevLevels };
+ delete newLevels[skillToRemove];
+ return newLevels;
+ });
+ };
+
+ const [skillLevels, setSkillLevels] = useState({});
+ const handleLevelChange = (skill, newLevel) => {
+ setSkillLevels(prevLevels => ({ ...prevLevels, [skill]: newLevel }));
+ };
+
+
+ useEffect(() => {
+ // Aktualizacja formData, aby zawierała skillLevels
+ setFormData(prevFormData => ({
+ ...prevFormData,
+ skillLevels: skillLevels
+ }));
+ }, [skillLevels]);
+
+ useEffect(() => {
+ // Jeśli formData zawiera już wybrane umiejętności i ich poziomy
+ if (formData.skillLevels) {
+ setSkillLevels(formData.skillLevels);
+ // Ustaw wybrane umiejętności na podstawie kluczy w formData.skillLevels
+ setSelectedSkills(Object.keys(formData.skillLevels));
+ }
+ }, []);
+
+ useEffect(() => {
+ console.log('Zaktualizowane poziomy umiejętności:', skillLevels);
+ }, [skillLevels, ]);
+
+ return (
+
+
+
+
+
+ {inputValue.length >= 1 && suggestions.length > 0 && (
+
+ {suggestions.map(suggestion => (
+
handleSuggestionClick(suggestion)}
+ className="w-56 h-max px-3 py-1 bg-slate-300 border-b-2 cursor-pointer"
+ >
+
{suggestion}
+
+ ))}
+
+
+ )}
+
+ {/* Lista wybranych umiejętności z możliwością określenia poziomu */}
+ {selectedSkills.map(skill => (
+
+
+ ))}
+
+ );
+};
+
+export default SkillsSelector;
\ No newline at end of file
diff --git a/src/components/StepFourJoblisting.jsx b/src/components/StepFourJoblisting.jsx
new file mode 100644
index 0000000..81e4314
--- /dev/null
+++ b/src/components/StepFourJoblisting.jsx
@@ -0,0 +1,120 @@
+import React from "react";
+import styles from "../style";
+import TextDivider from "./TextDivider";
+const StepFourJoblisting = ({ handleChange, formData, nextStep, prevStep }) => {
+ return (
+
+
+
+
+
+
+
+
+
+ Adres e-mail
+ *
+
+
+
+
+
+ Nazwa firmy
+ *
+
+
+
+
+
+
+
+ Nazwa firmy
+ *
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default StepFourJoblisting;
diff --git a/src/components/StepOneJoblisting.jsx b/src/components/StepOneJoblisting.jsx
new file mode 100644
index 0000000..4e3b670
--- /dev/null
+++ b/src/components/StepOneJoblisting.jsx
@@ -0,0 +1,68 @@
+import React from 'react'
+import styles from '../style'
+const StepOneJoblisting = ({ nextStep, handleChange, formData }) => {
+ // Funkcja do obsługi kliknięcia na div i aktualizacji stanu
+ const handleDivClick = (value) => () => {
+ handleChange('postingOption')({ target: { value: value } });
+ };
+
+ const activeStyle = "h-[500px] w-64 border-4 rounded-xl border-stone-200 bg-gray-200 div-transition scale-125";
+ const inactiveStyle = "h-[500px] w-64 rounded-xl bg-gray-200 border-gray-200 div-transition cursor-pointer hover:bg-gray-300"; // Dodaj tę samą klasę przejścia tutaj
+
+ return (
+
+ );
+};
+
+export default StepOneJoblisting
diff --git a/src/components/StepThreeJoblisting.jsx b/src/components/StepThreeJoblisting.jsx
new file mode 100644
index 0000000..056ea2f
--- /dev/null
+++ b/src/components/StepThreeJoblisting.jsx
@@ -0,0 +1,88 @@
+import React from 'react';
+import DOMPurify from 'dompurify';
+import styles from '../style';
+import TextDivider from './TextDivider';
+
+const StepThreeJoblisting = ({ formData, prevStep }) => {
+ // Funkcja do przetwarzania HTML i dodawania klas
+ const processHTML = (htmlString) => {
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(htmlString, 'text/html');
+
+ // Dodaj klasy do tagów h1, h2, ..., h6
+ doc.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach(tag => {
+ tag.classList.add('no-tailwindcss-base');
+ });
+
+ // Dodaj klasy do tagów ol, ul
+ doc.querySelectorAll('ol, ul').forEach(tag => {
+ tag.classList.add('no-tailwindcss-base');
+ });
+ doc.querySelectorAll('li').forEach(tag => {tag.classList.add('lista')})
+ return doc.body.innerHTML;
+ };
+
+ // Sanituj i przetwórz dane
+ const cleanAndProcessData = (userInput) => {
+ const sanitizedHTML = DOMPurify.sanitize(userInput);
+ return processHTML(sanitizedHTML);
+ };
+
+ // Przykład renderowania przetworzonej treści jako komponentów React
+ const renderContent = (htmlString) => {
+ return
;
+ };
+
+ return (
+
+
+ Wybrałeś opcję {formData.postingOption}
+
+
+
+
+
+
+
F.H.U. Januszex
+
12000 PLN - 15000 PLN
+
Starszy Inżynier ds. ciągłości produkcji
+
+
+
{cleanAndProcessData(formData.company_name)}
+ {
+ formData.requireSalary && (
{cleanAndProcessData(formData.minSalary)} PLN - {cleanAndProcessData(formData.maxSalary)} PLN
)
+ }
+ {
+ !formData.requireSalary && (
)
+ }
+
{cleanAndProcessData(formData.jobtitle)}
+
+
+
Papieżeks Sp. z o. o.
+
9000 PLN - 12000 PLN
+
Konstruktor - inżynier mechanik
+
+
+
+
+
+ {renderContent(formData.content)}
+
+
+
+
+ );
+}
+
+export default StepThreeJoblisting;
diff --git a/src/components/StepTwoJoblisting.jsx b/src/components/StepTwoJoblisting.jsx
new file mode 100644
index 0000000..4966aae
--- /dev/null
+++ b/src/components/StepTwoJoblisting.jsx
@@ -0,0 +1,178 @@
+import React, { useState } from 'react'
+import styles from '../style'
+import { CKEditor } from '@ckeditor/ckeditor5-react';
+import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
+import ImageUpload from './ImageUpload';
+import SkillsSelector from './SkillsSelector';
+import Salary from './Salary';
+
+const StepTwoJoblisting = ({ nextStep, prevStep, handleChange, formData, setFormData, removeFields }) => {
+ const [editorData, setEditorData] = useState('');
+ const handleEditorChange = (event, editor) => {
+ const data = editor.getData();
+ setEditorData(data);
+ }
+
+ const handleNextStep = () => {
+ if (validateForm()) {
+ console.log(errors)
+ nextStep(); // Przejście do następnego kroku
+ } else {
+ alert('Proszę wypełnić wszystkie wymagane pola.'); // Wyświetl komunikat o błędzie
+ }
+ };
+ const errorStyleInput = 'border-red-600'
+ const [errors, setErrors] = useState({});
+ const validateForm = () => {
+ let newErrors = {};
+
+ // Sprawdź każde wymagane pole
+ if (!formData.jobtitle) {
+ newErrors.jobtitle = 'To pole jest wymagane';
+ }
+ if (!formData.company_name) {
+ newErrors.company_name = 'To pole jest wymagane';
+ }
+ if (!formData.localization) {
+ newErrors.localization = 'To pole jest wymagane';
+ }
+ if (!formData.content) {
+ newErrors.content = 'To pole jest wymagane';
+ }
+ console.log(formData.requireSalary)
+ if (formData.requireSalary === true)
+ {
+ console.log(formData.requireSalary)
+ if (!formData.minSalary) {
+ newErrors.minSalary = 'To pole jest wymagane';
+ }
+ if (!formData.maxSalary) {
+ newErrors.maxSalary = 'To pole jest wymagane';
+ }
+ }
+
+ if (!formData.employmentType) {
+ newErrors.employmentType = 'To pole jest wymagane';
+ }
+ if (!formData.employmentType) {
+ newErrors.employmentType = 'To pole jest wymagane';
+ }
+ if (!formData.image) {
+ newErrors.image = 'To pole jest wymagane';
+ }
+ if (Object.keys(formData.skillLevels).length === 0) {
+ newErrors.skillLevels = 'To pole jest wymagane';
+ }
+ setErrors(newErrors);
+
+ // Zwróć true, jeśli nie ma błędów
+ return Object.keys(newErrors).length === 0;
+ };
+ return (
+ <>
+
+
+
+ Dodajesz ogłoszenie z izaac.pl
+
+
+
+
+
+ >
+ )
+}
+
+export default StepTwoJoblisting
diff --git a/src/components/TextDivider.jsx b/src/components/TextDivider.jsx
new file mode 100644
index 0000000..cdf4c84
--- /dev/null
+++ b/src/components/TextDivider.jsx
@@ -0,0 +1,16 @@
+import React from 'react'
+
+const TextDivider = ({text }) => {
+ return (
+
+
+ )
+}
+
+export default TextDivider
diff --git a/src/consts/index.js b/src/consts/index.js
index cdd51c5..54675c3 100644
--- a/src/consts/index.js
+++ b/src/consts/index.js
@@ -209,7 +209,7 @@ export const linki = [
},
{
"id": "2",
- "name": "work/jobpostings",
+ "name": "work/postings",
"title": "Ogłoszenia",
},
{
diff --git a/src/icon/android-chrome-192x192.png b/src/icon/android-chrome-192x192.png
new file mode 100644
index 0000000..9ee428f
Binary files /dev/null and b/src/icon/android-chrome-192x192.png differ
diff --git a/src/icon/android-chrome-512x512.png b/src/icon/android-chrome-512x512.png
new file mode 100644
index 0000000..ac0555d
Binary files /dev/null and b/src/icon/android-chrome-512x512.png differ
diff --git a/src/icon/apple-touch-icon.png b/src/icon/apple-touch-icon.png
new file mode 100644
index 0000000..df94305
Binary files /dev/null and b/src/icon/apple-touch-icon.png differ
diff --git a/src/icon/favicon-16x16.png b/src/icon/favicon-16x16.png
new file mode 100644
index 0000000..1e17d36
Binary files /dev/null and b/src/icon/favicon-16x16.png differ
diff --git a/src/icon/favicon-32x32.png b/src/icon/favicon-32x32.png
new file mode 100644
index 0000000..d3e103a
Binary files /dev/null and b/src/icon/favicon-32x32.png differ
diff --git a/src/icon/favicon.ico b/src/icon/favicon.ico
new file mode 100644
index 0000000..55b1408
Binary files /dev/null and b/src/icon/favicon.ico differ
diff --git a/src/icon/site.webmanifest b/src/icon/site.webmanifest
new file mode 100644
index 0000000..45dc8a2
--- /dev/null
+++ b/src/icon/site.webmanifest
@@ -0,0 +1 @@
+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
index c64826c..e56a6d4 100644
--- a/src/index.css
+++ b/src/index.css
@@ -25,6 +25,7 @@
@tailwind components;
@tailwind utilities;
+
:root {
--black-gradient: linear-gradient(
144.39deg,
@@ -38,20 +39,35 @@
scroll-behavior: smooth;
}
.editor-container {
-
margin-left: auto;
margin-right: auto;
- padding-left: 4rem;
- padding-right: 4rem;
+ padding-left: 12rem;
+ padding-right: 12rem;
+
;
}
-
+.div-transition {
+ transition: all 0.3s ease;
+ scale: 100%;
+}
.ck-editor__editable {
- min-height: 30rem;
+ min-height: 12rem;
+ max-height: 12rem;
+
}
-.ck.ck-editor {
- min-height: 140rem;
+
+.job-listing {
+ -webkit-mask-image: linear-gradient(to top, black 0%, transparent 100%);
+ mask-image: linear-gradient(to top, black 0%, transparent 100%);
+}
+.job-listing2 {
+ -webkit-mask-image: linear-gradient(to bottom, black 0%, transparent 100%);
+ mask-image: linear-gradient(to bottom, black 0%, transparent 100%);
+}
+
+.lista {
+ list-style: inside;
}
.sidebar-show {
diff --git a/src/style.js b/src/style.js
index 8f08a2a..062bfa1 100644
--- a/src/style.js
+++ b/src/style.js
@@ -1,6 +1,7 @@
const styles = {
boxWidth: "xl:max-w-[1280px] w-full",
boxWidth2: "w-full",
+ heading1: "font-poppins font-semibold xs:text-[40px] text-[40px] text-black xs:leading-[76.8px] leading-[66.8px] w-full",
heading2: "font-poppins font-semibold xs:text-[48px] text-[40px] text-black xs:leading-[76.8px] leading-[66.8px] w-full",
paragraph: "font-poppins font-normal text-black text-[18px] leading-[30.8px]",