diff --git a/sanity/schema.ts b/sanity/schema.ts index 686008d..c6294d8 100644 --- a/sanity/schema.ts +++ b/sanity/schema.ts @@ -1,10 +1,11 @@ import { type SchemaTypeDefinition } from 'sanity'; import job from '../src/schemas/job'; +import school from '../src/schemas/school'; import shortText from '../src/schemas/shortText'; import skill from '../src/schemas/skill'; import skillIcon from '../src/schemas/skillIcon'; export const schema: { types: SchemaTypeDefinition[] } = { - types: [job, shortText, skill, skillIcon], + types: [job, school, shortText, skill, skillIcon], }; diff --git a/src/app/(public)/about/page.tsx b/src/app/(public)/about/page.tsx index 189b960..6c88e2c 100644 --- a/src/app/(public)/about/page.tsx +++ b/src/app/(public)/about/page.tsx @@ -2,15 +2,18 @@ import { PortableText } from '@portabletext/react'; import Image from 'next/image'; import * as React from 'react'; +import Education from '@/components/organisms/Education/Education'; import WorkExperience from '@/components/organisms/WorkExperience/WorkExperience'; import { jobsQuery } from '@/queries/jobs'; +import { schoolsQuery } from '@/queries/schools'; import { shortTextQuery } from '@/queries/short-texts'; import { skillQuery } from '@/queries/skills'; import { sanityClient } from '../../../../sanity/lib/client'; import { Job } from '@/types/Job'; +import { School } from '@/types/School'; import { ShortText } from '@/types/ShortText'; import { Skill } from '@/types/Skill'; import { SkillIcon } from '@/types/SkillIcon'; @@ -23,19 +26,22 @@ export const metadata = { const getData = async () => { const jobs: Job[] = await sanityClient.fetch(jobsQuery); + const schools: School[] = await sanityClient.fetch(schoolsQuery); + const skills: Skill[] = await sanityClient.fetch(skillQuery); const shortTexts: ShortText[] = await sanityClient.fetch(shortTextQuery); return { jobs, + schools, shortTexts, skills, }; }; const AboutPage = async () => { - const { jobs, shortTexts, skills } = await getData(); + const { jobs, schools, shortTexts, skills } = await getData(); const softwareDevelopment: ShortText | undefined = shortTexts.find( (item) => item.name === 'software-development' @@ -107,6 +113,8 @@ const AboutPage = async () => { + + diff --git a/src/components/organisms/Education/Education.tsx b/src/components/organisms/Education/Education.tsx index 69e0de3..fc06918 100644 --- a/src/components/organisms/Education/Education.tsx +++ b/src/components/organisms/Education/Education.tsx @@ -1,14 +1,14 @@ 'use client'; -// import { PortableText } from '@portabletext/react'; -// import Image from 'next/image'; +import { PortableText } from '@portabletext/react'; +import Image from 'next/image'; // import {useTheme} from "next-themes"; import * as React from 'react'; -import { Job } from '@/types/Job'; +import { School } from '@/types/School'; export interface EducationProps { - schools: Job[]; + schools: School[]; } const Education = ({ schools }: EducationProps) => { @@ -20,60 +20,67 @@ const Education = ({ schools }: EducationProps) => {

Education

- {schools[0].isCurrentJob} +
+ {schools.map((school) => ( +
+ {/* Start School Header */} +
+ {school.schoolName} - {/*
*/} - {/* {jobs.map((job) => (*/} - {/*
*/} - {/* /!* Start Job Header *!/*/} - {/*
*/} - {/* */} +
+
+
+

+ {school.schoolName} +

- {/*
*/} - {/*
*/} - {/*

*/} - {/* {job.company} ~ {job.location}*/} - {/*

*/} - {/*
{job.jobTitle}
*/} - {/*
*/} + {school.schoolName} +
- {/*
*/} - {/*

*/} - {/* {job.startYear} – {job.isCurrentJob ? ` present` : job.endYear}*/} - {/*

*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/* /!* End Job Header *!/*/} +
{school.degreeName}
+
- {/* /!* Start Job Content *!/*/} - {/*
*/} - {/*
*/} - {/* */} - {/*
*/} +
+
+ + {school.grade} + +
- {/*
*/} - {/* {job.technologies.map((tech) => (*/} - {/* */} - {/* {tech}*/} - {/*
*/} - {/* ))}*/} - {/*
*/} - {/*
*/} - {/* /!* End Job Content *!/*/} - {/*
*/} - {/* ))}*/} - {/*
*/} +
+ + {school.startYear}  —  {school.endYear} + +
+
+
+
+ {/* End School Header */} + + {/* Start School Content */} +
+
+ +
+
+ {/* End School Content */} +
+ ))} + ); }; diff --git a/src/components/organisms/WorkExperience/WorkExperience.tsx b/src/components/organisms/WorkExperience/WorkExperience.tsx index 803ff4e..8b93c3e 100644 --- a/src/components/organisms/WorkExperience/WorkExperience.tsx +++ b/src/components/organisms/WorkExperience/WorkExperience.tsx @@ -39,16 +39,19 @@ const WorkExperience = ({ jobs }: WorkExperienceProps) => {

- {job.company} ~ {job.location} + {job.company} {job.location && `~`} {job.location}

{job.jobTitle}
-

- {job.startYear} –{' '} - {job.isCurrentJob ? ` present` : job.endYear} -

+ + <> + {format(job.startDate)} +   —   + {job.isCurrentJob ? `present` : format(job.endDate)} + +
@@ -83,4 +86,12 @@ const WorkExperience = ({ jobs }: WorkExperienceProps) => { ); }; +function format(inputDate: string): string { + const date = new Date(inputDate); + return Intl.DateTimeFormat('en', { + year: 'numeric', + month: 'short', + }).format(date); +} + export default WorkExperience; diff --git a/src/pages/api/schools.ts b/src/pages/api/schools.ts new file mode 100644 index 0000000..dd02be7 --- /dev/null +++ b/src/pages/api/schools.ts @@ -0,0 +1,15 @@ +import { NextApiRequest, NextApiResponse } from 'next'; + +import { schoolsQuery } from '@/queries/schools'; + +import { sanityClient } from '../../../sanity/lib/client'; + +import { School } from '@/types/School'; + +const schoolsApi = async (req: NextApiRequest, res: NextApiResponse) => { + const schools: School[] = await sanityClient.fetch(schoolsQuery); + + res.status(200).json(schools); +}; + +export default schoolsApi; diff --git a/src/queries/jobs.ts b/src/queries/jobs.ts index cc77a7c..3bd91cb 100644 --- a/src/queries/jobs.ts +++ b/src/queries/jobs.ts @@ -1,14 +1,14 @@ import { groq } from 'next-sanity'; export const jobsQuery = groq` -*[_type == "job"] | order(endYear desc) { +*[_type == "job"] | order(endDate desc) { _id, company, "iconUrl": icon.asset->url, location, jobTitle, - startYear, - endYear, + startDate, + endDate, isCurrentJob, description, technologies, diff --git a/src/queries/schools.ts b/src/queries/schools.ts new file mode 100644 index 0000000..38ebc16 --- /dev/null +++ b/src/queries/schools.ts @@ -0,0 +1,16 @@ +import { groq } from 'next-sanity'; + +export const schoolsQuery = groq` +*[_type == "school"] | order(endYear desc) { + _id, + name, + schoolName, + "schoolIcon": schoolIcon.asset->url, + "flagUrl": countryFlag.asset->url, + degreeName, + degreeUrl, + grade, + startYear, + endYear, + description, +}`; diff --git a/src/schemas/job.ts b/src/schemas/job.ts index 450e38d..b55ee9a 100644 --- a/src/schemas/job.ts +++ b/src/schemas/job.ts @@ -31,16 +31,22 @@ export default defineType({ type: 'string', }), defineField({ - name: 'startYear', - title: 'Start Year', - type: 'number', - initialValue: new Date().getFullYear() - 3, + name: 'startDate', + title: 'Start Date', + type: 'date', + options: { + dateFormat: 'MMM YYYY', + }, + initialValue: 'Mar 2020', }), defineField({ - name: 'endYear', + name: 'endDate', title: 'End Year', - type: 'number', - initialValue: new Date().getFullYear() - 1, + type: 'date', + options: { + dateFormat: 'MMM YYYY', + }, + initialValue: 'Mar 2022', }), defineField({ name: 'isCurrentJob', @@ -81,7 +87,7 @@ export default defineType({ { title: 'Most Recent', name: 'jobDateDesc', - by: [{ field: 'endYear', direction: 'desc' }], + by: [{ field: 'startDate', direction: 'desc' }], }, ], }); diff --git a/src/schemas/school.ts b/src/schemas/school.ts new file mode 100644 index 0000000..977747c --- /dev/null +++ b/src/schemas/school.ts @@ -0,0 +1,69 @@ +import { defineField, defineType } from 'sanity'; + +export default defineType({ + name: 'school', + title: 'School', + type: 'document', + fields: [ + defineField({ + name: 'name', + title: 'Name', + type: 'string', + }), + defineField({ + name: 'schoolName', + title: 'School Name', + type: 'string', + }), + defineField({ + name: 'schoolIcon', + title: 'School Icon', + type: 'image', + }), + defineField({ + name: 'countryFlag', + title: 'Country Flag', + type: 'image', + }), + defineField({ + name: 'degreeName', + title: 'Degree Name', + type: 'string', + }), + defineField({ + name: 'degreeUrl', + title: 'Degree Url', + type: 'string', + }), + defineField({ + name: 'grade', + title: 'Grade', + type: 'string', + }), + defineField({ + name: 'startYear', + title: 'Start Year', + type: 'number', + initialValue: new Date().getFullYear() - 5, + }), + defineField({ + name: 'endYear', + title: 'End Year', + type: 'number', + initialValue: new Date().getFullYear() - 3, + }), + defineField({ + name: 'description', + title: 'Description', + type: 'array', + of: [{ type: 'block' }], + }), + ], + orderings: [ + { + title: 'Most Recent', + name: 'schoolDateDesc', + by: [{ field: 'endYear', direction: 'desc' }], + }, + ], +}); diff --git a/src/types/Job.ts b/src/types/Job.ts index 79a48d0..b37d680 100644 --- a/src/types/Job.ts +++ b/src/types/Job.ts @@ -7,8 +7,8 @@ export interface Job { iconUrl: string; location: string; jobTitle: string; - startYear: number; - endYear: number; + startDate: string; + endDate: string; isCurrentJob: boolean; description: TypedObject; mainColor: string; diff --git a/src/types/School.ts b/src/types/School.ts new file mode 100644 index 0000000..178719b --- /dev/null +++ b/src/types/School.ts @@ -0,0 +1,15 @@ +import { TypedObject } from '@portabletext/types'; + +export interface School { + _id: string; + name: string; + schoolName: string; + schoolIcon: string; + flagUrl: string; + degreeName: string; + degreeUrl: string; + grade: string; + startYear: number; + endYear: number; + description: TypedObject; +}