feat: overhaul
This commit is contained in:
BIN
public/portfolio/work_profile.png
Normal file
BIN
public/portfolio/work_profile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
@@ -1,7 +1,7 @@
|
|||||||
import Intro from "@/src/portfolio/sections/Intro";
|
import Intro from "@/src/portfolio/sections/Intro";
|
||||||
import Projects from "@/src/portfolio/sections/Projects";
|
import Projects from "@/src/portfolio/sections/Projects";
|
||||||
import Experience from "@/src/portfolio/sections/Experience";
|
import Experience from "@/src/portfolio/sections/Experience";
|
||||||
import Achievements from "@/src/portfolio/sections/Achievements";
|
import CurrentWork from "@/src/portfolio/sections/CurrentWork";
|
||||||
import Footer from "@/src/portfolio/sections/Footer";
|
import Footer from "@/src/portfolio/sections/Footer";
|
||||||
import SkillsAndLinks from "@/src/portfolio/sections/SkillsAndLinks";
|
import SkillsAndLinks from "@/src/portfolio/sections/SkillsAndLinks";
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ const MainPage = (): JSX.Element => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Intro/>
|
<Intro/>
|
||||||
<Achievements/>
|
<CurrentWork/>
|
||||||
<Experience/>
|
<Experience/>
|
||||||
<Projects/>
|
<Projects/>
|
||||||
<SkillsAndLinks/>
|
<SkillsAndLinks/>
|
||||||
|
|||||||
26
src/portfolio/data/currentWorkData.ts
Normal file
26
src/portfolio/data/currentWorkData.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
export interface ICurrentWorkData {
|
||||||
|
role: string;
|
||||||
|
company: string;
|
||||||
|
companyUrl: string;
|
||||||
|
specialization: string;
|
||||||
|
location: string;
|
||||||
|
imagePath: string;
|
||||||
|
paragraphs: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentWorkData: ICurrentWorkData = {
|
||||||
|
role: "Technical Consultant",
|
||||||
|
company: "Softwire",
|
||||||
|
companyUrl: "https://www.softwire.com/",
|
||||||
|
specialization: "AI Engineering",
|
||||||
|
location: "Manchester, United Kingdom",
|
||||||
|
imagePath: "/portfolio/work_profile.png",
|
||||||
|
paragraphs: [
|
||||||
|
"I spend much of my time <strong>designing and evaluating AI systems</strong>, or systems where AI plays a central role. My work involves the full lifecycle of AI implementation, from initial concept through to production deployment.",
|
||||||
|
"I have <strong>delivered training and adoption materials</strong> that have significantly improved AI usage within Softwire, helping teams understand both the capabilities and limitations of AI technologies. I've also created <strong>autonomous AI pipelines</strong> that have reduced developer burden by automating tasks that were previously time-consuming manual processes.",
|
||||||
|
"Working with <strong>diverse clients</strong> (from the highly skeptical to the enthusiastically optimistic), I've developed expertise in <strong>communicating AI benefits</strong> while respecting organizational constraints. This involves not just technical implementation, but also the human and ethical dimensions of AI adoption.",
|
||||||
|
"A particular area of passion for me is <strong>Ethical AI and Sustainable AI</strong>. I've spent considerable time advocating for sustainability considerations in AI systems, conducting <strong>environmental assessments for embedded AI</strong>, and building adoption systems that leverage <strong>local open-source AI</strong> instead of relying on large providers whose ethical standards can be questionable."
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default currentWorkData;
|
||||||
@@ -13,7 +13,7 @@ const projectData : IProjectArguments[] = [
|
|||||||
],
|
],
|
||||||
github: "https://github.com/KuchtaVR6/Multi-LLM-Agent",
|
github: "https://github.com/KuchtaVR6/Multi-LLM-Agent",
|
||||||
document: "/multiAgent.pdf",
|
document: "/multiAgent.pdf",
|
||||||
title: "Research Review of Neural Techniques for low-resource language translation",
|
title: "Multi-LLM Tool Use – Modular Pipeline with Expert Adapters",
|
||||||
text: "In this work, I explore a practical and cost-effective approach to improving how AI models interact with external tools and APIs. Instead of relying on large, expensive models or complex zero-shot learning methods, I utilize a modular pipeline using smaller, specialized components (Planner, Caller, Summariser) trained separately. I introduce to it a hard routing agent system that assigns tasks to expert adapters based on API categories, the system achieves performance that surpasses much larger closed-source models on a key benchmark. This approach enables more efficient, decentralized training and has potential applications beyond the tool-use QA task."
|
text: "In this work, I explore a practical and cost-effective approach to improving how AI models interact with external tools and APIs. Instead of relying on large, expensive models or complex zero-shot learning methods, I utilize a modular pipeline using smaller, specialized components (Planner, Caller, Summariser) trained separately. I introduce to it a hard routing agent system that assigns tasks to expert adapters based on API categories, the system achieves performance that surpasses much larger closed-source models on a key benchmark. This approach enables more efficient, decentralized training and has potential applications beyond the tool-use QA task."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
import { WorkExperienceArgs } from "@/src/portfolio/helpers/WorkExperience";
|
import { WorkExperienceArgs } from "@/src/portfolio/helpers/WorkExperience";
|
||||||
|
|
||||||
const workExperienceData : WorkExperienceArgs[] = [
|
const workExperienceData : WorkExperienceArgs[] = [
|
||||||
|
{
|
||||||
|
industry: "Software & AI",
|
||||||
|
title: "Technical Consultant",
|
||||||
|
company: "Softwire",
|
||||||
|
city: "Manchester",
|
||||||
|
country: "United Kingdom",
|
||||||
|
startDate: "November 2025"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
industry: "Software & AI",
|
industry: "Software & AI",
|
||||||
title: "Software Developer",
|
title: "Software Developer",
|
||||||
company: "Softwire",
|
company: "Softwire",
|
||||||
city: "Manchester",
|
city: "Manchester",
|
||||||
country: "United Kingdom",
|
country: "United Kingdom",
|
||||||
startDate: "November 2024"
|
startDate: "November 2024",
|
||||||
|
endDate: "November 2025"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
industry: "Artificial Intelligence",
|
industry: "Artificial Intelligence",
|
||||||
@@ -109,8 +118,8 @@ export const workExperienceParagraph =
|
|||||||
"Mentor at Queen Mary University, where I later became a Laboratory Demonstrator. In the software industry, " +
|
"Mentor at Queen Mary University, where I later became a Laboratory Demonstrator. In the software industry, " +
|
||||||
"I gained experience as a Software Developer Intern at Softwire. During my master's degree, I contributed to " +
|
"I gained experience as a Software Developer Intern at Softwire. During my master's degree, I contributed to " +
|
||||||
"the Artificial Intelligence industry as a Programming Data Annotator at DataAnnotation Tech. Upon graduation, " +
|
"the Artificial Intelligence industry as a Programming Data Annotator at DataAnnotation Tech. Upon graduation, " +
|
||||||
"I accepted a full-time offer to join Softwire as a Software Developer in their North West office in Manchester, " +
|
"I accepted a full-time offer to join Softwire as a Software Developer in their North West office in Manchester. " +
|
||||||
"known for its focus on innovation in the AI and Data sector. At Softwire, I have gained valuable experience " +
|
"In November 2025, I transitioned to Technical Consultant, AI Specialist. At Softwire, I have gained valuable experience " +
|
||||||
"working on several AI projects, applying my theoretical machine learning knowledge to real-world problems. " +
|
"working on several AI projects, applying my theoretical machine learning knowledge to real-world problems. " +
|
||||||
"Across these diverse roles, I have developed a strong work ethic and a broad set of transferable skills.";
|
"Across these diverse roles, I have developed a strong work ethic and a broad set of transferable skills.";
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { FC, useState } from "react";
|
import React, { FC, useState } from "react";
|
||||||
import { CSSTransition } from "react-transition-group";
|
import { CSSTransition } from "react-transition-group";
|
||||||
|
import { FaChevronDown, FaChevronUp } from "react-icons/fa";
|
||||||
|
|
||||||
type AccordionArgs = {
|
type AccordionArgs = {
|
||||||
title : string,
|
title : string,
|
||||||
@@ -16,8 +17,10 @@ const Accordion : FC<AccordionArgs> = ({ title, children }): JSX.Element => {
|
|||||||
return (
|
return (
|
||||||
<div className="accordion">
|
<div className="accordion">
|
||||||
<div className="accordion-header" onClick={toggleAccordion}>
|
<div className="accordion-header" onClick={toggleAccordion}>
|
||||||
<h2>{title} {isOpen ? "-" : "+"}</h2>
|
<h2>{title}</h2>
|
||||||
<span></span>
|
<span className="accordion-icon">
|
||||||
|
{isOpen ? <FaChevronUp /> : <FaChevronDown />}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<CSSTransition in={isOpen} timeout={0} classNames="accordion-content" unmountOnExit>
|
<CSSTransition in={isOpen} timeout={0} classNames="accordion-content" unmountOnExit>
|
||||||
<div className="accordion-content">{children}</div>
|
<div className="accordion-content">{children}</div>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import styles from "../styling/achievements.module.scss";
|
import styles from "../styling/currentWork.module.scss";
|
||||||
|
import Location from "./Location";
|
||||||
|
|
||||||
export type EducationArgs = {
|
export type EducationArgs = {
|
||||||
institution : string,
|
institution : string,
|
||||||
@@ -14,48 +15,42 @@ export type EducationArgs = {
|
|||||||
|
|
||||||
const Education : FC<EducationArgs> = (props) => {
|
const Education : FC<EducationArgs> = (props) => {
|
||||||
|
|
||||||
const getCountryEmoji = (): string => {
|
const getLocationString = (): string => {
|
||||||
switch (props.city) {
|
switch (props.city) {
|
||||||
case "Warsaw":
|
case "Warsaw":
|
||||||
return ", Poland";
|
return "Warsaw, Poland";
|
||||||
case "London":
|
case "London":
|
||||||
return ", UK";
|
return "London, UK";
|
||||||
case "Edinburgh":
|
case "Edinburgh":
|
||||||
return ", UK";
|
return "Edinburgh, UK";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ fontSize: "1.1em" }} className={styles.education} data-aos={"fade-right"}>
|
<div className={styles.educationEntry} data-aos={"fade-up"}>
|
||||||
<div>
|
<div className={styles.degree}>
|
||||||
<span className={styles.title}>{props.title}</span> in <b>{props.subtitle}</b>
|
{props.title} in {props.subtitle}
|
||||||
<br/>
|
</div>
|
||||||
at <i>{props.institution}</i>
|
<div className={styles.institution}>
|
||||||
{props.notes?
|
at {props.institution}
|
||||||
<ul className={styles.notes}>
|
</div>
|
||||||
{props.notes.map((note, index) =>
|
{props.notes && (
|
||||||
<li key={index}>
|
<ul className={styles.notes}>
|
||||||
{note}
|
{props.notes.map((note, index) => (
|
||||||
</li>
|
<li key={index}>{note}</li>
|
||||||
)}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
: ""
|
)}
|
||||||
}
|
<div className={styles.details}>
|
||||||
|
<Location city={getLocationString()} className={styles.location} />
|
||||||
|
<div className={styles.dates}>
|
||||||
|
{props.endDate ? (
|
||||||
|
<span>{props.startDate} - {props.endDate}</span>
|
||||||
|
) : (
|
||||||
|
<span>Since {props.startDate}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span className={styles.otherDetails}>
|
|
||||||
<div className={styles.location}>{props.city}{getCountryEmoji()}</div>
|
|
||||||
<hr/>
|
|
||||||
{props.endDate ?
|
|
||||||
<>
|
|
||||||
<i>From: </i>
|
|
||||||
<span style={{ float:"right" }}>{props.startDate}</span>
|
|
||||||
<br/>
|
|
||||||
<i>To: </i>
|
|
||||||
<span style={{ float:"right" }}>{props.endDate}</span>
|
|
||||||
</>:
|
|
||||||
"Since " + props.startDate
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
18
src/portfolio/helpers/Location.tsx
Normal file
18
src/portfolio/helpers/Location.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { FaMapMarkerAlt } from "react-icons/fa";
|
||||||
|
|
||||||
|
interface ILocationProps {
|
||||||
|
city: string;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Location: FC<ILocationProps> = ({ city, className }) => {
|
||||||
|
return (
|
||||||
|
<span className={className} style={{ display: "flex", alignItems: "center", gap: "0.3rem" }}>
|
||||||
|
<FaMapMarkerAlt style={{ fontSize: "0.7em" }} />
|
||||||
|
{city}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Location;
|
||||||
69
src/portfolio/sections/CurrentWork.tsx
Normal file
69
src/portfolio/sections/CurrentWork.tsx
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import Image from "next/image";
|
||||||
|
import styles from "../styling/currentWork.module.scss";
|
||||||
|
import currentWorkData from "@/src/portfolio/data/currentWorkData";
|
||||||
|
import educationData from "@/src/portfolio/data/educationData";
|
||||||
|
import Education from "@/src/portfolio/helpers/Education";
|
||||||
|
import Location from "@/src/portfolio/helpers/Location";
|
||||||
|
|
||||||
|
const RoleInfo = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className={styles.roleInfo}>
|
||||||
|
<h3>{currentWorkData.role}</h3>
|
||||||
|
<p className={styles.specialization}>
|
||||||
|
Specializing in <strong>{currentWorkData.specialization}</strong>
|
||||||
|
</p>
|
||||||
|
<p className={styles.company}>
|
||||||
|
at{" "}
|
||||||
|
<a
|
||||||
|
href={currentWorkData.companyUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className={styles.companyLink}
|
||||||
|
>
|
||||||
|
{currentWorkData.company}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<div className={styles.locationWrapper}>
|
||||||
|
<Location city={currentWorkData.location} className={styles.location} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CurrentWork = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className={styles.section} id={"current-work"}>
|
||||||
|
<div className={styles.mainContent}>
|
||||||
|
<div className={styles.currentWorkSection}>
|
||||||
|
<h2>What I'm Up To</h2>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<div className={styles.imageContainer} data-aos={"fade-right"}>
|
||||||
|
<div className={styles.imageWrapper}>
|
||||||
|
<Image
|
||||||
|
src={currentWorkData.imagePath}
|
||||||
|
alt="Patryk Kuchta at work"
|
||||||
|
fill={true}
|
||||||
|
className={styles.profileImage}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<RoleInfo />
|
||||||
|
</div>
|
||||||
|
<div className={styles.description} data-aos={"fade-left"}>
|
||||||
|
{currentWorkData.paragraphs.map((paragraph, index) => (
|
||||||
|
<p key={index} dangerouslySetInnerHTML={{ __html: paragraph }} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.educationSection}>
|
||||||
|
<h2>Education</h2>
|
||||||
|
{educationData.map((entry, index) => (
|
||||||
|
<Education {...entry} key={index} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CurrentWork;
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
|
import Image from "next/image";
|
||||||
import styles from "../styling/footer.module.scss";
|
import styles from "../styling/footer.module.scss";
|
||||||
|
|
||||||
const Footer = (): JSX.Element => {
|
const Footer = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<footer className={styles.section}>
|
<footer className={styles.section}>
|
||||||
Copyright © Patryk Kuchta {new Date().getFullYear()}
|
<div className={styles.logoWrapper}>
|
||||||
|
<Image
|
||||||
|
src="/portfolio/white_logo.png"
|
||||||
|
alt="Patryk Kuchta Logo"
|
||||||
|
fill={true}
|
||||||
|
className={styles.logo}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p>Copyright © Patryk Kuchta {new Date().getFullYear()}</p>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,68 +1,67 @@
|
|||||||
import styles from "../../styling/skillsLinks.module.scss";
|
import styles from "../../styling/skillsLinks.module.scss";
|
||||||
|
import { FaGithub, FaLinkedin, FaFilePdf, FaEnvelope } from "react-icons/fa";
|
||||||
|
|
||||||
interface ILink {
|
interface ILink {
|
||||||
title: string;
|
title: string;
|
||||||
link: string;
|
link: string;
|
||||||
|
icon: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const moreInfoLinks: ILink[] = [
|
const moreInfoLinks: ILink[] = [
|
||||||
{
|
{
|
||||||
title: "Github",
|
title: "Github",
|
||||||
link: "https://github.com/KuchtaVR6/"
|
link: "https://github.com/KuchtaVR6/",
|
||||||
|
icon: <FaGithub />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "LinkedIn",
|
title: "LinkedIn",
|
||||||
link: "https://linkedin.com/in/kuchtap"
|
link: "https://linkedin.com/in/kuchtap",
|
||||||
|
icon: <FaLinkedin />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Curriculum Vitae",
|
title: "Curriculum Vitae",
|
||||||
link: "/PatrykKuchta_CV.pdf"
|
link: "/PatrykKuchta_CV.pdf",
|
||||||
|
icon: <FaFilePdf />
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const contactLinks: ILink[] = [
|
const contactLinks: ILink[] = [
|
||||||
{
|
{
|
||||||
title: "Email",
|
title: "Email",
|
||||||
link: "mailto:patryk@kuchta.uk"
|
link: "mailto:patryk@kuchta.uk",
|
||||||
|
icon: <FaEnvelope />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "LinkedIn",
|
title: "LinkedIn",
|
||||||
link: "https://linkedin.com/in/kuchtap"
|
link: "https://linkedin.com/in/kuchtap",
|
||||||
|
icon: <FaLinkedin />
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const LinksSection = (): JSX.Element => {
|
const LinksSection = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div data-aos = {"fade-right"} className={styles.otherLinks}>
|
<div data-aos={"fade-right"} className={styles.otherLinks}>
|
||||||
<h2>Find out more about me:</h2>
|
<h2>Find out more about me:</h2>
|
||||||
<ul>
|
<ul>
|
||||||
{
|
{moreInfoLinks.map(({ title, link, icon }, key) => (
|
||||||
moreInfoLinks.map(({ title, link }, key) => {
|
<li key={key}>
|
||||||
return (
|
<a href={link} className={styles.linkWithIcon}>
|
||||||
<li key = {key}>
|
<span className={styles.icon}>{icon}</span>
|
||||||
<a href={link}>
|
{title}
|
||||||
{title}
|
</a>
|
||||||
</a>
|
</li>
|
||||||
</li>
|
))}
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Contact me through:</h2>
|
<h2>Contact me through:</h2>
|
||||||
<ul>
|
<ul>
|
||||||
{
|
{contactLinks.map(({ title, link, icon }, key) => (
|
||||||
contactLinks.map(({ title, link }, key) => {
|
<li key={key}>
|
||||||
return (
|
<a href={link} className={styles.linkWithIcon}>
|
||||||
<li key = {key}>
|
<span className={styles.icon}>{icon}</span>
|
||||||
<a href={link}>
|
{title}
|
||||||
{title}
|
</a>
|
||||||
</a>
|
</li>
|
||||||
</li>
|
))}
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,41 +1,58 @@
|
|||||||
import styles from "../../styling/skillsLinks.module.scss";
|
import styles from "../../styling/skillsLinks.module.scss";
|
||||||
import SkillDisplay from "@/src/portfolio/helpers/SkillDisplay";
|
|
||||||
import Accordion from "@/src/portfolio/helpers/Accordion";
|
import Accordion from "@/src/portfolio/helpers/Accordion";
|
||||||
import { skillsInCategories } from "@/src/portfolio/data/skillsData";
|
import { skillsInCategories } from "@/src/portfolio/data/skillsData";
|
||||||
import { modulesTaken } from "@/src/portfolio/data/modulesTaken";
|
import { modulesTaken } from "@/src/portfolio/data/modulesTaken";
|
||||||
|
import certificateData from "@/src/portfolio/data/certificateData";
|
||||||
|
|
||||||
|
const renderSkillItem = (name: string, level: string): JSX.Element => (
|
||||||
|
<div className={styles.technology} key={name}>
|
||||||
|
<b>{name}</b>
|
||||||
|
<span style={{ float: "right", fontSize: "0.8em" }}>
|
||||||
|
<i>{level}</i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
const SkillsSection = (): JSX.Element => {
|
const SkillsSection = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div data-aos = {"fade-left"} className={styles.skills}>
|
<div data-aos={"fade-left"} className={styles.skills}>
|
||||||
<div>
|
|
||||||
<i>Press the "+" to expand a section</i> 👀
|
|
||||||
</div>
|
|
||||||
<div className={styles.innerskills}>
|
<div className={styles.innerskills}>
|
||||||
{
|
<Accordion title={"Certificates and Awards"}>
|
||||||
Object.entries(skillsInCategories).map(([category, skills]) => {
|
{certificateData.map(({ title, institution, awardDate }, index) => (
|
||||||
return <Accordion title={category} key={category}>
|
<div className={styles.technology} key={index}>
|
||||||
{
|
<b>{title}</b>
|
||||||
skills.map((skill) => {
|
<span style={{ float: "right", fontSize: "0.8em" }}>
|
||||||
return <SkillDisplay {...skill} key={skill.name} />;
|
<i>{institution}</i> - {awardDate}
|
||||||
})
|
</span>
|
||||||
}
|
</div>
|
||||||
</Accordion>;
|
))}
|
||||||
})
|
</Accordion>
|
||||||
}
|
|
||||||
|
|
||||||
<Accordion title={"Modules Taken"}>
|
<Accordion title={"Modules Taken"}>
|
||||||
{
|
{modulesTaken.map(({ name, level, score }) => (
|
||||||
modulesTaken.map(({ name, level, score }) => {
|
<div id={name.toLowerCase()} className={styles.technology} key={name}>
|
||||||
return <div id={name.toLowerCase()}
|
<b>{name}</b>
|
||||||
className={styles.technology}
|
<span style={{ float: "right", fontSize: "0.8em" }}>
|
||||||
key={name}>
|
{score >= 0 ? score + "%" : "N/A"} <i>{level}</i>
|
||||||
<b>{name} </b>
|
</span>
|
||||||
<span style={{ float: "right", fontSize: "0.8em" }}>
|
</div>
|
||||||
{score>=0? score + "%" : "🔮"} <i>{level}</i>
|
))}
|
||||||
</span>
|
</Accordion>
|
||||||
</div>;
|
|
||||||
})
|
<Accordion title={"Human languages"}>
|
||||||
}
|
{skillsInCategories["Human languages"].map((skill) => renderSkillItem(skill.name, skill.level))}
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title={"Programming Languages"}>
|
||||||
|
{skillsInCategories["Programming Languages"].map((skill) => renderSkillItem(skill.name, skill.level))}
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title={"Frameworks/Libraries"}>
|
||||||
|
{skillsInCategories["Frameworks/Libraries"].map((skill) => renderSkillItem(skill.name, skill.level))}
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title={"Miscellaneous"}>
|
||||||
|
{skillsInCategories["Miscellaneous"].map((skill) => renderSkillItem(skill.name, skill.level))}
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,8 +21,6 @@
|
|||||||
.education {
|
.education {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background-color: transparentize($gray, 0.5);
|
background-color: transparentize($gray, 0.5);
|
||||||
padding: 1em;
|
|
||||||
margin: 1em;
|
|
||||||
border-radius: $smallGap;
|
border-radius: $smallGap;
|
||||||
box-shadow: 0.5em 0.5em transparentize($black, 0.5);
|
box-shadow: 0.5em 0.5em transparentize($black, 0.5);
|
||||||
|
|
||||||
|
|||||||
245
src/portfolio/styling/currentWork.module.scss
Normal file
245
src/portfolio/styling/currentWork.module.scss
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
@import "/src/styles/helpers";
|
||||||
|
|
||||||
|
.section {
|
||||||
|
@include lightSection;
|
||||||
|
@include regularFont;
|
||||||
|
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
color: $accent_colour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainContent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3rem;
|
||||||
|
max-width: 1400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
@media (min-width: 1280px) {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 1.5rem;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.currentWorkSection {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 1rem;
|
||||||
|
|
||||||
|
@media (min-width: 1280px) {
|
||||||
|
flex: 0 0 54%;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
padding-left: 0;
|
||||||
|
border-right: 2px solid $accent_colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
color: $accent_colour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.educationSection {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 1rem;
|
||||||
|
|
||||||
|
@media (min-width: 1280px) {
|
||||||
|
flex: 0 0 42%;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1279px) {
|
||||||
|
padding-top: 2rem;
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
border-top: 2px solid $accent_colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
margin-top: 0;
|
||||||
|
color: $accent_colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
.educationEntry {
|
||||||
|
background-color: transparentize($gray, 0.85);
|
||||||
|
padding: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 3px solid $accent_colour;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.degree {
|
||||||
|
font-weight: bold;
|
||||||
|
color: $accent_colour;
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.institution {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notes {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.details {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
.location {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dates {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
@media (min-width: 900px) {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 2rem;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 899px) {
|
||||||
|
align-items: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
@media (min-width: 900px) {
|
||||||
|
flex: 0 0 25%;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageWrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profileImage {
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
border: 4px solid $accent_colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roleInfo {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: $accent_colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.specialization {
|
||||||
|
font-style: italic;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.locationWrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.location {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.companyLink {
|
||||||
|
color: rgb(0, 214, 254);
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.8rem;
|
||||||
|
|
||||||
|
@media (min-width: 900px) {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
line-height: 1.7;
|
||||||
|
text-align: justify;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
@media (max-width: 899px) {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
width: 42em;
|
width: 42em;
|
||||||
max-width: 70vw;
|
max-width: 70vw;
|
||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,35 @@
|
|||||||
@import "@/src/styles/helpers.scss";
|
@import "@/src/styles/helpers.scss";
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
@include darkSection;
|
@include darkSection;
|
||||||
@include regularFont;
|
@include regularFont;
|
||||||
|
|
||||||
padding: 0.4em;
|
display: flex;
|
||||||
text-align: center;
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 2rem;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logoWrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 2rem;
|
||||||
|
height: 1rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
object-fit: contain;
|
||||||
|
opacity: 0.7;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,53 +1,103 @@
|
|||||||
@import "@/src/styles/helpers.scss";
|
@import "@/src/styles/helpers.scss";
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
@include lightSection;
|
@include lightSection;
|
||||||
@include regularFont;
|
@include regularFont;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
padding: 0 6em 3em;
|
padding: 3rem 2rem;
|
||||||
|
|
||||||
.skills {
|
@media (max-width: 768px) {
|
||||||
display: flex;
|
padding: 2rem 1rem;
|
||||||
flex-direction: column;
|
}
|
||||||
text-align: center;
|
|
||||||
.innerskills {
|
|
||||||
text-align: left;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
gap: $mediumGap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
flex-basis: 60%;
|
|
||||||
}
|
|
||||||
flex-wrap: wrap;
|
|
||||||
flex-basis: 60%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.otherLinks{
|
.skills {
|
||||||
margin: auto 1em;
|
display: flex;
|
||||||
padding: 1em 2em;
|
flex-direction: column;
|
||||||
background-color: $black;
|
text-align: center;
|
||||||
color: $white;
|
flex-basis: 60%;
|
||||||
|
min-width: 300px;
|
||||||
|
|
||||||
h2{
|
@media (max-width: 768px) {
|
||||||
font-size: 115%;
|
flex-basis: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
.innerskills {
|
||||||
color: $white;
|
text-align: left;
|
||||||
text-decoration: none;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
.otherLinks {
|
||||||
color: $accent_colour;
|
margin: auto 1em;
|
||||||
font-style: italic;
|
padding: 1.5em 2.5em;
|
||||||
}
|
background-color: $black;
|
||||||
}
|
color: $white;
|
||||||
}
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $white;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $accent_colour;
|
||||||
|
transform: translateX(5px);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkWithIcon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.technology {
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
border-bottom: 1px solid transparentize($gray, 0.5);
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,30 +43,74 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.accordion {
|
||||||
|
border: 1px solid transparentize($gray, 0.3);
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: $white;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
transition: box-shadow 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-header {
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: transparentize($gray, 0.7);
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
user-select: none;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: transparentize($gray, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: $black;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: $accent_colour;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-content {
|
||||||
|
padding: 1.5rem;
|
||||||
|
background-color: $white;
|
||||||
|
}
|
||||||
|
|
||||||
.accordion-content-enter {
|
.accordion-content-enter {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
height: 0;
|
max-height: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-content-enter-active {
|
.accordion-content-enter-active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
height: auto;
|
max-height: 2000px;
|
||||||
transition: opacity 300ms, height 300ms;
|
transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-content-exit {
|
.accordion-content-exit {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
height: auto;
|
max-height: 2000px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-content-exit-active {
|
.accordion-content-exit-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
height: 0;
|
max-height: 0;
|
||||||
transition: opacity 300ms, height 300ms;
|
transition: opacity 300ms ease-in-out, max-height 300ms ease-in-out;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-header {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user