feat: new components, style, etc

This commit is contained in:
Mike 2024-06-22 13:17:36 -04:00
parent c3184ad970
commit 148d037942
11 changed files with 235 additions and 121 deletions

View file

@ -2,9 +2,9 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title> <title>CV-Creator</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View file

@ -0,0 +1,68 @@
:root {
--font-size: 16px;
--default-border-radius: 0.5rem;
/* Shadows */
--default-shadow: 0 4px 6px hsla(0, 0%, 0%, 0.2);
--small-shadow: 0 1px 3px hsla(0, 0%, 0%, 0.2);
--large-shadow: 0 15px 35px hsla(0, 0%, 0%, 0.2);
--tight-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
--wide-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
/* Grays */
--lightest-gray: 208, 21%, 93%;
--lighter-gray: 210, 16%, 76%;
--light-gray: 208, 12%, 58%;
--dark-gray: 207, 12%, 43%;
--darker-gray: 209, 15%, 28%;
--white-color: 360, 100%, 100%;
}
html,
body {
padding: 0;
margin: 0;
font-size: var(--font-size);
background: hsl(var(--lightest-gray));
}
.container {
display: flex;
justify-content: center;
padding: 24px;
gap: 30px;
}
.resume {
min-width: 800px;
/* background: gray; */
}
.form {
max-width: 450px;
min-width: 400px;
}
.general-info-form {
padding: 20px;
margin-bottom: 1rem;
border-radius: var(--default-border-radius);
box-shadow: var(--tight-shadow), var(--wide-shadow);
background: hsl(var(--white-color));
}
.basic-info {
display: flex;
flex-direction: column;
align-items: center;
}
.basic-info p {
padding: 0;
margin: 0;
}
.basic-info-details {
display: flex;
gap: 1rem;
}

View file

@ -3,18 +3,21 @@ import GeneralInfoDisplay from "./components/generalInfoDisplay";
import EducationInfoDisplay from "./components/educationInfoDisplay"; import EducationInfoDisplay from "./components/educationInfoDisplay";
import EducationInfoForm from "./components/educationInfoForm"; import EducationInfoForm from "./components/educationInfoForm";
import ExperienceForm from "./components/experienceForm"; import ExperienceForm from "./components/experienceForm";
import ExperienceDisplay from "./components/experienceDisplay";
import "./App.css"; import "./App.css";
import { useState } from "react"; import { useState } from "react";
function App() { function App() {
const [basicInfo, setBasicInfo] = useState({ const [basicInfo, setBasicInfo] = useState({
firstName: "", fullName: "Marvin Gaye",
lastName: "", phone: "301-240-5555",
phone: "", email: "mgaye@motown.com",
email: "", location: "Detriot, MI",
}); });
const [educationInfo, setEducationInfo] = useState([]); const [educationInfo, setEducationInfo] = useState([]);
const [editEducation, setEditEducation] = useState(null); const [editEducation, setEditEducation] = useState(null);
const [employmentHistory, setEmploymentHistory] = useState([]);
return ( return (
<div className="container"> <div className="container">
@ -26,7 +29,10 @@ function App() {
setEditEducation={setEditEducation} setEditEducation={setEditEducation}
editEducation={editEducation} editEducation={editEducation}
/> />
<ExperienceForm /> <ExperienceForm
employmentHistory={employmentHistory}
setEmploymentHistory={setEmploymentHistory}
/>
</div> </div>
<div className="resume"> <div className="resume">
<GeneralInfoDisplay basicInfo={basicInfo} /> <GeneralInfoDisplay basicInfo={basicInfo} />
@ -35,6 +41,7 @@ function App() {
setEditEducation={setEditEducation} setEditEducation={setEditEducation}
setEducationInfo={setEducationInfo} setEducationInfo={setEducationInfo}
/> />
<ExperienceDisplay employmentHistory={employmentHistory} />
</div> </div>
</div> </div>
); );

View file

@ -1,31 +1,25 @@
export default function EducationInfoDisplay(props) { export default function EducationInfoDisplay(props) {
return ( return (
<div> <>
{props.educationInfo.length <= 0 ? ( <EducationDisplay
<> educationInfo={props.educationInfo}
<p>Add your Education info</p> setEducationInfo={props.setEducationInfo}
</> setEditEducation={props.setEditEducation}
) : ( />
<EducationDisplay </>
educationInfo={props.educationInfo}
setEducationInfo={props.setEducationInfo}
setEditEducation={props.setEditEducation}
/>
)}
</div>
); );
} }
function EducationDisplay(props) { function EducationDisplay(props) {
return ( return (
<div> <>
{props.educationInfo.map((item) => { {props.educationInfo.map((item) => {
return ( return (
<div key={item.schoolName} className="education-info"> <div key={item.schoolName} className="education-info">
<h2>School: {item.schoolName}</h2> <h2>School: {item.schoolName}</h2>
<p> <p>
Graduation Date: {item.graduationDate + " "} Graduation: {item.graduationDate + " "}
Field of Study: {item.fieldOfStudy} Degree: {item.fieldOfStudy}
<button onClick={() => props.setEditEducation(item)}>edit</button> <button onClick={() => props.setEditEducation(item)}>edit</button>
<button <button
onClick={() => onClick={() =>
@ -42,7 +36,7 @@ function EducationDisplay(props) {
</div> </div>
); );
})} })}
</div> </>
); );
} }

View file

@ -1,9 +1,7 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
export default function EducationInfoForm(props) { export default function EducationInfoForm(props) {
// const [schools, setSchools] = useState([]);
const [educationItemActive, setEducationItemActive] = useState(false); const [educationItemActive, setEducationItemActive] = useState(false);
// const [editSchool, setEditSchool] = useState(null);
return ( return (
<div className="education-info section"> <div className="education-info section">
@ -50,15 +48,12 @@ function EducationForm({
}, [editSchool]); }, [editSchool]);
let schoolId = editSchool let schoolId = editSchool
? educationInfo.findIndex( ? educationInfo.findIndex((school) => school.id === editSchool.id)
(school) => school.schoolName === editSchool.schoolName,
)
: null; : null;
const contactFormStyle = { const contactFormStyle = {
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "30vw",
}; };
return ( return (
@ -68,19 +63,19 @@ function EducationForm({
<form action="" style={contactFormStyle}> <form action="" style={contactFormStyle}>
<input <input
type="text" type="text"
placeholder="School Name" placeholder="Enter university/school"
value={schoolName} value={schoolName}
onChange={(e) => setSchoolName(e.target.value)} onChange={(e) => setSchoolName(e.target.value)}
/> />
<input <input
type="text" type="text"
placeholder="Graduation Date" placeholder="Enter graduation date"
value={graduationDate} value={graduationDate}
onChange={(e) => setGraduationDate(e.target.value)} onChange={(e) => setGraduationDate(e.target.value)}
/> />
<input <input
type="text" type="text"
placeholder="Field of Study" placeholder="Enter degree/field of study"
value={fieldOfStudy} value={fieldOfStudy}
onChange={(e) => setFieldOfStudy(e.target.value)} onChange={(e) => setFieldOfStudy(e.target.value)}
/> />
@ -103,6 +98,7 @@ function EducationForm({
schoolName: schoolName, schoolName: schoolName,
fieldOfStudy: fieldOfStudy, fieldOfStudy: fieldOfStudy,
graduationDate: graduationDate, graduationDate: graduationDate,
id: crypto.randomUUID(),
}, },
]); ]);
} }
@ -120,6 +116,7 @@ function EducationForm({
setGraduationDate(""); setGraduationDate("");
setSchoolName(""); setSchoolName("");
setFieldOfStudy(""); setFieldOfStudy("");
schoolId = null;
}} }}
> >
Clear Clear

View file

@ -0,0 +1,26 @@
export default function ExperienceDisplay(props) {
return (
<div className="job-info">
<JobList jobs={props.employmentHistory} />
</div>
);
}
function JobList(props) {
return (
<>
{props.jobs.map((item) => {
return (
<div className="job" key={item.id}>
<h2>{item.employer}</h2>
<h3>{item.jobTitle}</h3>
<p>
{item.employmentStart} - {item.employmentEnd}
</p>
<p>{item.jobDescription}</p>
</div>
);
})}
</>
);
}

View file

@ -1,49 +1,23 @@
import { useState } from "react"; import { useState } from "react";
export default function ExperienceForm() { export default function ExperienceForm(props) {
const [jobs, setJobs] = useState([]); // const [jobs, setJobs] = useState([]);
const [showJobForm, setShowJobForm] = useState(false); const [showJobForm, setShowJobForm] = useState(false);
const mainDivStyle = {
display: "flex",
justifyContent: "space-between",
flexDirection: "row-reverse",
};
return ( return (
<div className="jobs" style={mainDivStyle}> <div className="Job-info-form">
<div className="job-info"> <button onClick={() => setShowJobForm(!showJobForm)}>
<JobList jobs={jobs} /> Add Employer Info
</div> </button>
<div className="Job-info-form"> <JobForm
<button onClick={() => setShowJobForm(!showJobForm)}> setJobs={props.setEmploymentHistory}
Add Employer Info jobs={props.employmentHistory}
</button> isActive={showJobForm}
<JobForm setJobs={setJobs} jobs={jobs} isActive={showJobForm} /> />
</div>
</div> </div>
); );
} }
function JobList(props) {
return (
<>
{props.jobs.map((item) => {
return (
<div className="job" key={item.id}>
<h2>{item.employer}</h2>
<h3>{item.jobTitle}</h3>
<p>
{item.employmentStart} - {item.employmentEnd}
</p>
<p>{item.jobDescription}</p>
</div>
);
})}
</>
);
}
function JobForm({ isActive, jobs, setJobs }) { function JobForm({ isActive, jobs, setJobs }) {
const [employer, setEmployer] = useState(""); const [employer, setEmployer] = useState("");
const [jobTitle, setJobTitle] = useState(""); const [jobTitle, setJobTitle] = useState("");
@ -54,7 +28,6 @@ function JobForm({ isActive, jobs, setJobs }) {
const formStyle = { const formStyle = {
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "30vw",
}; };
function clear() { function clear() {
@ -68,7 +41,8 @@ function JobForm({ isActive, jobs, setJobs }) {
function handleSubmit(event, stuff) { function handleSubmit(event, stuff) {
event.preventDefault(); event.preventDefault();
const newJob = { ...stuff }; const key = crypto.randomUUID();
const newJob = { ...stuff, id: key };
setJobs([...jobs, newJob]); setJobs([...jobs, newJob]);

View file

@ -2,17 +2,16 @@ export default function GeneralInfoDisplay(props) {
const basicInfo = props.basicInfo; const basicInfo = props.basicInfo;
return ( return (
<> <>
{ {basicInfo ? (
basicInfo ? <div className="basic-info">
( <h1>{basicInfo.fullName}</h1>
<div className="basic-info" > <div className="basic-info-details">
<h1>{basicInfo.firstName + " " + basicInfo.lastName}</h1> <p>{basicInfo.location}</p>
<p>{basicInfo.email}</p> <p>{basicInfo.email}</p>
<p>{basicInfo.phone}</p> <p>{basicInfo.phone}</p>
</div> </div>
) : null </div>
} ) : null}
</> </>
);
)
} }

View file

@ -1,68 +1,83 @@
import { useState } from "react"; import { useState } from "react";
import Input from "./input";
export default function GeneralInfoForm(props) { export default function GeneralInfoForm(props) {
const [firstName, setFirstName] = useState(""); const [fullName, setFullName] = useState("");
const [lastName, setLastName] = useState(""); const [location, setLocation] = useState("");
const [phone, setPhone] = useState(""); const [phone, setPhone] = useState("");
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
const contactFormStyle = { const contactFormStyle = {
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "30vw",
};
const mainStyle = {
display: "flex",
justifyContent: "space-between",
}; };
return ( return (
<div className="general-info section" style={mainStyle}> <>
<div className="contact-info-form"> <div className="general-info-form">
<form action=""> <form action="">
<div style={contactFormStyle}> <div style={contactFormStyle}>
<input <h2 className="general-info-header">Personal Details</h2>
type="text" <Input
placeholder="First Name" label={true}
value={firstName} name="fullName"
labelName="Full name"
value={fullName}
placeholder=""
onChange={(e) => { onChange={(e) => {
setFirstName(e.target.value) setFullName(e.target.value);
props.setBasicInfo({ ...props.basicInfo, firstName: e.target.value }) props.setBasicInfo({
} ...props.basicInfo,
} fullName: e.target.value,
});
}}
/> />
<input <Input
type="text" label={true}
placeholder="Last Name" name="location"
value={lastName} labelName="Location"
placeholder=""
value={location}
onChange={(e) => { onChange={(e) => {
setLastName(e.target.value) setLocation(e.target.value);
props.setBasicInfo({ ...props.basicInfo, lastName: e.target.value }) props.setBasicInfo({
}} /> ...props.basicInfo,
<input location: e.target.value,
});
}}
/>
<Input
label={true}
type="email" type="email"
placeholder="Email" name="email"
labelName="Email"
placeholder=""
value={email} value={email}
onChange={(e) => { onChange={(e) => {
setEmail(e.target.value) setEmail(e.target.value);
props.setBasicInfo({ ...props.basicInfo, email: e.target.value }) props.setBasicInfo({
} ...props.basicInfo,
} email: e.target.value,
});
}}
/> />
<input <Input
type="text" type="text"
placeholder="Phone Number" label={true}
labelName="Phone"
placeholder=""
value={phone} value={phone}
onChange={(e) => { onChange={(e) => {
setPhone(e.target.value) setPhone(e.target.value);
props.setBasicInfo({ ...props.basicInfo, phone: e.target.value }) props.setBasicInfo({
...props.basicInfo,
phone: e.target.value,
});
}} }}
/> />
</div> </div>
</form> </form>
</div> </div>
</>
</div>
); );
} }

View 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>
);
}

View file

@ -0,0 +1,15 @@
.input {
display: flex;
flex-direction: column;
font-size: 1.3rem;
line-height: 1.3;
}
.input label {
padding: 10px 0 5px 0;
font-size: 1rem;
}
.input input {
font-size: 1.3rem;
}