mirror of
https://gitea.smigz.com/smiggiddy/odin-codeprojects.git
synced 2025-06-28 12:55:36 -04:00
Cv project (#17)
* feat: updated component * feat: added components * feat: fixed * refactor(feat): added button, renamed variables * feat: updated education info component * feat: experience component added * refactor: modular * feat: new components, style, etc * refactor: remove unneccessary divs * feat(styling): yep * feat(style): new font added for resume * feat(styling): colors, btns, etc * feat: basically done
This commit is contained in:
parent
940deff071
commit
592ddc4c1f
29 changed files with 5621 additions and 0 deletions
9
cv-project/src/components/button.jsx
Normal file
9
cv-project/src/components/button.jsx
Normal file
|
@ -0,0 +1,9 @@
|
|||
import "../styles/button.css";
|
||||
|
||||
export default function Button(props) {
|
||||
return (
|
||||
<button className={`${props.className} + btn`} onClick={props.onClick}>
|
||||
{props.text}
|
||||
</button>
|
||||
);
|
||||
}
|
49
cv-project/src/components/educationInfoDisplay.jsx
Normal file
49
cv-project/src/components/educationInfoDisplay.jsx
Normal file
|
@ -0,0 +1,49 @@
|
|||
export default function EducationInfoDisplay(props) {
|
||||
return (
|
||||
<div className="education-info">
|
||||
<h2>Education</h2>
|
||||
<EducationDisplay
|
||||
educationInfo={props.educationInfo}
|
||||
setEducationInfo={props.setEducationInfo}
|
||||
setEditEducation={props.setEditEducation}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function EducationDisplay(props) {
|
||||
return (
|
||||
<>
|
||||
{props.educationInfo.map((item) => {
|
||||
return (
|
||||
<div key={item.schoolName} className="education-item">
|
||||
<h2>{item.schoolName}</h2>
|
||||
<p>
|
||||
Graduation: {item.graduationDate + " "}
|
||||
{item.fieldOfStudy}
|
||||
</p>
|
||||
<button onClick={() => props.setEditEducation(item)}>edit</button>
|
||||
<button
|
||||
onClick={() =>
|
||||
deleteEducationItem(
|
||||
props.educationInfo,
|
||||
item.schoolName,
|
||||
props.setEducationInfo,
|
||||
)
|
||||
}
|
||||
>
|
||||
remove
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function deleteEducationItem(educationInfo, item, setEducationInfo) {
|
||||
const filteredSchools = educationInfo.filter(
|
||||
(school) => school.schoolName !== item,
|
||||
);
|
||||
setEducationInfo(filteredSchools);
|
||||
}
|
136
cv-project/src/components/educationInfoForm.jsx
Normal file
136
cv-project/src/components/educationInfoForm.jsx
Normal file
|
@ -0,0 +1,136 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import Input from "./input";
|
||||
import Button from "./button";
|
||||
|
||||
export default function EducationInfoForm(props) {
|
||||
return (
|
||||
<>
|
||||
<EducationForm
|
||||
isActive={props.educationItemActive}
|
||||
educationInfo={props.educationInfo}
|
||||
setEducationInfo={props.setEducationInfo}
|
||||
editSchool={props.editEducation}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function EducationForm({
|
||||
isActive,
|
||||
educationInfo,
|
||||
setEducationInfo,
|
||||
editSchool,
|
||||
}) {
|
||||
const [graduationDate, setGraduationDate] = useState("");
|
||||
const [schoolName, setSchoolName] = useState("");
|
||||
const [fieldOfStudy, setFieldOfStudy] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (editSchool) {
|
||||
setGraduationDate(editSchool.graduationDate);
|
||||
setSchoolName(editSchool.schoolName);
|
||||
setFieldOfStudy(editSchool.fieldOfStudy);
|
||||
} else {
|
||||
setGraduationDate("");
|
||||
setSchoolName("");
|
||||
setFieldOfStudy("");
|
||||
}
|
||||
}, [editSchool]);
|
||||
|
||||
let schoolId = editSchool
|
||||
? educationInfo.findIndex((school) => school.id === editSchool.id)
|
||||
: null;
|
||||
|
||||
const contactFormStyle = {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{isActive ? (
|
||||
<div className="education-info-form">
|
||||
<h2 className="general-info-header">Education History</h2>
|
||||
<form
|
||||
action=""
|
||||
style={contactFormStyle}
|
||||
onSubmit={(e) => console.log(e.target)}
|
||||
>
|
||||
<Input
|
||||
label={true}
|
||||
labelName="School"
|
||||
name="School"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={schoolName}
|
||||
onChange={(e) => setSchoolName(e.target.value)}
|
||||
/>
|
||||
<Input
|
||||
label={true}
|
||||
labelName="Graduation date"
|
||||
name="graduationDate"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={graduationDate}
|
||||
onChange={(e) => setGraduationDate(e.target.value)}
|
||||
/>
|
||||
<Input
|
||||
label={true}
|
||||
labelName="Degree/Field of study"
|
||||
name="degree"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={fieldOfStudy}
|
||||
onChange={(e) => setFieldOfStudy(e.target.value)}
|
||||
/>
|
||||
<div className="btn-group">
|
||||
<Button
|
||||
autoFocus={true}
|
||||
type="submit"
|
||||
className="submit-btn"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
console.log(schoolName, graduationDate, fieldOfStudy);
|
||||
const updatedSchools = [...educationInfo];
|
||||
if (schoolId !== -1 && schoolId !== null) {
|
||||
updatedSchools[schoolId] = {
|
||||
schoolName: schoolName,
|
||||
graduationDate: graduationDate,
|
||||
fieldOfStudy: fieldOfStudy,
|
||||
};
|
||||
setEducationInfo(updatedSchools);
|
||||
} else {
|
||||
setEducationInfo([
|
||||
...educationInfo,
|
||||
{
|
||||
schoolName: schoolName,
|
||||
fieldOfStudy: fieldOfStudy,
|
||||
graduationDate: graduationDate,
|
||||
id: crypto.randomUUID(),
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
setGraduationDate("");
|
||||
setSchoolName("");
|
||||
setFieldOfStudy("");
|
||||
}}
|
||||
text="Submit"
|
||||
/>
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setGraduationDate("");
|
||||
setSchoolName("");
|
||||
setFieldOfStudy("");
|
||||
schoolId = null;
|
||||
}}
|
||||
text="Clear"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
29
cv-project/src/components/experienceDisplay.jsx
Normal file
29
cv-project/src/components/experienceDisplay.jsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
export default function ExperienceDisplay(props) {
|
||||
return (
|
||||
<div className="job-info">
|
||||
<h2>Experience</h2>
|
||||
<JobList jobs={props.employmentHistory} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function JobList(props) {
|
||||
return (
|
||||
<>
|
||||
{props.jobs.map((item) => {
|
||||
return (
|
||||
<div className="job" key={item.id}>
|
||||
<div className="job-details">
|
||||
<h2 className="job-employer">{item.employer}</h2>
|
||||
<p className="job-dates">
|
||||
{item.employmentStart} - {item.employmentEnd}
|
||||
</p>
|
||||
</div>
|
||||
<h3 className="job-title">{item.jobTitle}</h3>
|
||||
<p>{item.jobDescription}</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
128
cv-project/src/components/experienceForm.jsx
Normal file
128
cv-project/src/components/experienceForm.jsx
Normal file
|
@ -0,0 +1,128 @@
|
|||
import { useState } from "react";
|
||||
import Input from "./input";
|
||||
import Button from "./button";
|
||||
|
||||
export default function ExperienceForm(props) {
|
||||
return (
|
||||
<>
|
||||
<JobForm
|
||||
setJobs={props.setEmploymentHistory}
|
||||
jobs={props.employmentHistory}
|
||||
isActive={props.showJobForm}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function JobForm({ isActive, jobs, setJobs }) {
|
||||
const [employer, setEmployer] = useState("");
|
||||
const [jobTitle, setJobTitle] = useState("");
|
||||
const [jobDescription, setJobDescription] = useState([]);
|
||||
const [employmentStart, setEmploymentStart] = useState("");
|
||||
const [employmentEnd, setEmploymentEnd] = useState("");
|
||||
|
||||
const formStyle = {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
|
||||
function clear() {
|
||||
setEmployer("");
|
||||
setJobTitle("");
|
||||
setJobDescription("");
|
||||
setEmploymentEnd("");
|
||||
setEmploymentStart("");
|
||||
}
|
||||
|
||||
function handleSubmit(event, stuff) {
|
||||
event.preventDefault();
|
||||
|
||||
const key = crypto.randomUUID();
|
||||
const newJob = { ...stuff, id: key };
|
||||
|
||||
setJobs([...jobs, newJob]);
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isActive ? (
|
||||
<div className="job-info-form">
|
||||
<h2 className="general-info-header">Employment History</h2>
|
||||
<form action="" style={formStyle}>
|
||||
<Input
|
||||
name="employer"
|
||||
label={true}
|
||||
labelName="Employer"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={employer}
|
||||
onChange={(e) => setEmployer(e.target.value)}
|
||||
/>
|
||||
<Input
|
||||
name="jobTitle"
|
||||
label={true}
|
||||
labelName="Job title"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={jobTitle}
|
||||
onChange={(e) => setJobTitle(e.target.value)}
|
||||
/>
|
||||
<Input
|
||||
name="startDate"
|
||||
label={true}
|
||||
labelName="Start date"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={employmentStart}
|
||||
onChange={(e) => setEmploymentStart(e.target.value)}
|
||||
/>
|
||||
<Input
|
||||
name="endDate"
|
||||
label={true}
|
||||
labelName="End date"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={employmentEnd}
|
||||
onChange={(e) => setEmploymentEnd(e.target.value)}
|
||||
/>
|
||||
<div className="input">
|
||||
<label>Description</label>
|
||||
<textarea
|
||||
name="jobDescription"
|
||||
value={jobDescription}
|
||||
onChange={(e) => setJobDescription(e.target.value)}
|
||||
rows="5"
|
||||
maxLength="400"
|
||||
/>
|
||||
</div>
|
||||
<div className="btn-group">
|
||||
<Button
|
||||
onClick={(e) =>
|
||||
handleSubmit(e, {
|
||||
employer,
|
||||
jobTitle,
|
||||
jobDescription,
|
||||
employmentStart,
|
||||
employmentEnd,
|
||||
})
|
||||
}
|
||||
className="submit-btn"
|
||||
text="Submit"
|
||||
/>
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
clear();
|
||||
}}
|
||||
className="clear-btn"
|
||||
text="Clear"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
17
cv-project/src/components/generalInfoDisplay.jsx
Normal file
17
cv-project/src/components/generalInfoDisplay.jsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
export default function GeneralInfoDisplay(props) {
|
||||
const basicInfo = props.basicInfo;
|
||||
return (
|
||||
<>
|
||||
{basicInfo ? (
|
||||
<div className="basic-info">
|
||||
<h1>{basicInfo.fullName}</h1>
|
||||
<div className="basic-info-details">
|
||||
<p>{basicInfo.location}</p>
|
||||
<p>{basicInfo.email}</p>
|
||||
<p>{basicInfo.phone}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
83
cv-project/src/components/generalInfoForm.jsx
Normal file
83
cv-project/src/components/generalInfoForm.jsx
Normal file
|
@ -0,0 +1,83 @@
|
|||
import { useState } from "react";
|
||||
import Input from "./input";
|
||||
|
||||
export default function GeneralInfoForm(props) {
|
||||
const [fullName, setFullName] = useState(props.basicInfo.fullName);
|
||||
const [location, setLocation] = useState(props.basicInfo.location);
|
||||
const [phone, setPhone] = useState(props.basicInfo.phone);
|
||||
const [email, setEmail] = useState(props.basicInfo.email);
|
||||
|
||||
const contactFormStyle = {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="general-info-form">
|
||||
<form action="">
|
||||
<div style={contactFormStyle}>
|
||||
<h2 className="general-info-header">Personal Details</h2>
|
||||
<Input
|
||||
label={true}
|
||||
name="fullName"
|
||||
labelName="Full name"
|
||||
value={fullName}
|
||||
placeholder=""
|
||||
onChange={(e) => {
|
||||
setFullName(e.target.value);
|
||||
props.setBasicInfo({
|
||||
...props.basicInfo,
|
||||
fullName: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
label={true}
|
||||
name="location"
|
||||
labelName="Location"
|
||||
placeholder=""
|
||||
value={location}
|
||||
onChange={(e) => {
|
||||
setLocation(e.target.value);
|
||||
props.setBasicInfo({
|
||||
...props.basicInfo,
|
||||
location: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
label={true}
|
||||
type="email"
|
||||
name="email"
|
||||
labelName="Email"
|
||||
placeholder=""
|
||||
value={email}
|
||||
onChange={(e) => {
|
||||
setEmail(e.target.value);
|
||||
props.setBasicInfo({
|
||||
...props.basicInfo,
|
||||
email: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
type="text"
|
||||
label={true}
|
||||
labelName="Phone"
|
||||
placeholder=""
|
||||
value={phone}
|
||||
onChange={(e) => {
|
||||
setPhone(e.target.value);
|
||||
props.setBasicInfo({
|
||||
...props.basicInfo,
|
||||
phone: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
19
cv-project/src/components/input.jsx
Normal file
19
cv-project/src/components/input.jsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import "../styles/input.css";
|
||||
|
||||
export default function Input(props) {
|
||||
return (
|
||||
<div className="input">
|
||||
{props.label ? (
|
||||
<label htmlFor={props.name}>{props.labelName}</label>
|
||||
) : null}
|
||||
<input
|
||||
name={props.name}
|
||||
id={props.name}
|
||||
type={props.type}
|
||||
value={props.value}
|
||||
onChange={props.onChange}
|
||||
placeholder={props.placeholder}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue