Skip to content

Commit

Permalink
feat: updated project details
Browse files Browse the repository at this point in the history
- added project type indicator
  • Loading branch information
schaechinger committed Dec 6, 2023
1 parent 2046fbb commit c97abb0
Show file tree
Hide file tree
Showing 16 changed files with 302 additions and 187 deletions.
2 changes: 1 addition & 1 deletion app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const Sidebar = () => (
<ul className="flex flex-col gap-2 py-2">
{ [
{ link: '/#ueber-mich', label: 'Über mich' },
{ link: '/lebenslauf', label: 'Lebenslauf' },
{ link: '/lebenslauf', label: 'Berufserfahrung' },
{ link: '/projekte', label: 'Projekte' },
{ link: '/kontakt', label: 'Kontakt' },
].map((item) => (
Expand Down
2 changes: 0 additions & 2 deletions app/components/career/CompanyLink.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Link from 'next/link';

import { Company } from '@/models/career';

const CompanyLink = ({ company }: { company?: Company }) => {
Expand Down
9 changes: 9 additions & 0 deletions app/components/icons/Banknotes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Icon, { IconProps } from './Icon';

const Banknotes = (props: IconProps) => (
<Icon { ...props }>
<path id="banknotes" d="M20.46313,25.6745l-13.20434,4.806a.987.987,0,0,1-.3418.061,1.0001,1.0001,0,0,1-.93945-.65869l-.72382-1.98864c.0163.00024.03168.00427.048.00427a3.03431,3.03431,0,0,0,.52344-.0459l1.44842-.25537.241.66211L11.2702,26.8924,20.36,25.28961A.2.2,0,0,1,20.46313,25.6745Zm-14.98559.2088L19.57733,23.397A.2.2,0,0,0,19.5426,23h-9.232l-4.19538.73975L5.98474,23H4c-.016,0-.03094-.00452-.04694-.00476l.36628,2.077a.99923.99923,0,0,0,.98339.82617A1.01512,1.01512,0,0,0,5.47754,25.8833ZM19,13.5A3.5,3.5,0,1,1,15.5,10,3.5,3.5,0,0,1,19,13.5Zm-2,0A1.5,1.5,0,1,0,15.5,15,1.50172,1.50172,0,0,0,17,13.5ZM28,6.87274V20.12726A.87275.87275,0,0,1,27.12726,21H3.87274A.87275.87275,0,0,1,3,20.12726V6.87274A.87275.87275,0,0,1,3.87274,6H27.12726A.87275.87275,0,0,1,28,6.87274ZM5,9.99072A1.78826,1.78826,0,0,0,5.18182,10a2.00547,2.00547,0,0,0,.491-.06323A1.79129,1.79129,0,0,0,6.93646,8.67389,1.93161,1.93161,0,0,0,6.991,8H5Zm1.93677,8.33637a1.79132,1.79132,0,0,0-1.26288-1.26355A2.00467,2.00467,0,0,0,5.18188,17,1.78856,1.78856,0,0,0,5,17.00928V19H6.991A1.93426,1.93426,0,0,0,6.93677,18.32709ZM26,17.00928A1.78826,1.78826,0,0,0,25.81818,17a2.00547,2.00547,0,0,0-.491.06323,1.79129,1.79129,0,0,0-1.26361,1.26288A1.93161,1.93161,0,0,0,24.009,19H26Zm0-5.02362c-.06116.00293-.11993.01434-.18182.01434a3.99283,3.99283,0,0,1-.98432-.12506A3.79173,3.79173,0,0,1,22.12439,9.1637,3.89006,3.89006,0,0,1,22.02515,8H8.97473a3.889,3.889,0,0,1-.09979,1.16614A3.79173,3.79173,0,0,1,6.1637,11.87561,3.99492,3.99492,0,0,1,5.18182,12c-.06189,0-.12066-.01141-.18182-.01434v3.02868C5.06116,15.01141,5.11993,15,5.18188,15a3.99236,3.99236,0,0,1,.98426.12506A3.79173,3.79173,0,0,1,8.87561,17.8363,3.89006,3.89006,0,0,1,8.97485,19H22.02527a3.889,3.889,0,0,1,.09979-1.16614,3.79173,3.79173,0,0,1,2.71124-2.70947A3.99492,3.99492,0,0,1,25.81818,15c.06189,0,.12066.01141.18182.01434ZM26,8H24.009a1.93426,1.93426,0,0,0,.0542.67291,1.79132,1.79132,0,0,0,1.26288,1.26355A2.003,2.003,0,0,0,25.81818,10,1.78568,1.78568,0,0,0,26,9.99078Z"/>
</Icon>
)

export default Banknotes;
11 changes: 11 additions & 0 deletions app/components/icons/BuildingsCity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { SVGProps } from 'react';

import Icon from './Icon';

const BuildingsCity = (props: SVGProps<SVGSVGElement>) => (
<Icon { ...props }>
<path id="buildings-city" d="M21,4H11A2.00006,2.00006,0,0,0,9,6V27.5a.5.5,0,0,0,.5.5H13V25a1.00291,1.00291,0,0,1,1-1h4a1.00291,1.00291,0,0,1,1,1v3h3.5a.5.5,0,0,0,.5-.5V6A2.00006,2.00006,0,0,0,21,4ZM15,20.5a.5.5,0,0,1-.5.5h-2a.5.5,0,0,1-.5-.5v-2a.5.5,0,0,1,.5-.5h2a.5.5,0,0,1,.5.5Zm0-5a.5.5,0,0,1-.5.5h-2a.5.5,0,0,1-.5-.5v-2a.5.5,0,0,1,.5-.5h2a.5.5,0,0,1,.5.5Zm0-5a.5.5,0,0,1-.5.5h-2a.5.5,0,0,1-.5-.5v-2a.5.5,0,0,1,.5-.5h2a.5.5,0,0,1,.5.5Zm5,10a.5.5,0,0,1-.5.5h-2a.5.5,0,0,1-.5-.5v-2a.5.5,0,0,1,.5-.5h2a.5.5,0,0,1,.5.5Zm0-5a.5.5,0,0,1-.5.5h-2a.5.5,0,0,1-.5-.5v-2a.5.5,0,0,1,.5-.5h2a.5.5,0,0,1,.5.5Zm0-5a.5.5,0,0,1-.5.5h-2a.5.5,0,0,1-.5-.5v-2a.5.5,0,0,1,.5-.5h2a.5.5,0,0,1,.5.5ZM30,10V27.5a.5.5,0,0,1-.5.5H25V25h1.5a.5.5,0,0,0,.5-.5v-2a.5.5,0,0,0-.5-.5H25V20h1.5a.5.5,0,0,0,.5-.5v-2a.5.5,0,0,0-.5-.5H25V15h1.5a.5.5,0,0,0,.5-.5v-2a.5.5,0,0,0-.5-.5H25V8h3A2.00006,2.00006,0,0,1,30,10ZM7,28H2.5a.5.5,0,0,1-.5-.5V13a2.00006,2.00006,0,0,1,2-2H7v4H5.5a.5.5,0,0,0-.5.5v2a.5.5,0,0,0,.5.5H7v2H5.5a.5.5,0,0,0-.5.5v2a.5.5,0,0,0,.5.5H7Z"/>
</Icon>
)

export default BuildingsCity;
11 changes: 11 additions & 0 deletions app/components/icons/HandHeart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { SVGProps } from 'react';

import Icon from './Icon';

const HandHeart = (props: SVGProps<SVGSVGElement>) => (
<Icon { ...props }>
<path id="hand-heart" d="M15.12823,6.8363c0-2.28656,3.1164-3.923,4.78656-1.58191a.10686.10686,0,0,0,.17377.00226A2.63608,2.63608,0,0,1,24.87177,6.8363c0,1.99585-2.53718,3.58985-4.56421,5.81757a.41344.41344,0,0,1-.61512,0C17.66541,10.42615,15.12823,8.83215,15.12823,6.8363ZM5.70709,19.70709a1,1,0,0,0-1.41418,0L2,22l7,7,2.29291-2.29291a1,1,0,0,0,0-1.41418Zm24.18549-1.76373a1.49865,1.49865,0,0,0-1.94922-.83594l-3.10065,1.24024-3.86517,1.57812A1.00233,1.00233,0,0,1,20.59961,20H16a1,1,0,0,1,0-2h4.40332l1.19867-.48938A1.49495,1.49495,0,0,0,20.5,15H17l-3.32709-.86523a1.99977,1.99977,0,0,0-1.28668.17187L9.28955,15.85535a1.998,1.998,0,0,0-.519.37414L7,18l6,6h5.5a1.49157,1.49157,0,0,0,.55664-.10742l10-4A1.49946,1.49946,0,0,0,29.89258,17.94336Z"/>
</Icon>
)

export default HandHeart;
5 changes: 4 additions & 1 deletion app/components/icons/Icon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { SVGProps } from 'react';

const Icon = (props: SVGProps<SVGSVGElement>) => (
export type IconProps = SVGProps<SVGSVGElement> & { title?: string };

const Icon = (props: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 32 32"
Expand All @@ -11,6 +13,7 @@ const Icon = (props: SVGProps<SVGSVGElement>) => (
className: `inline-block${props.className ? ` ${props.className}` : ''}`,
style: { ...(props.style || {}), fill: 'currentColor' },
children: undefined,
title: props.title,
} }
>{ props.children }</svg>
)
Expand Down
9 changes: 9 additions & 0 deletions app/components/icons/Knight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Icon, { IconProps } from './Icon';

const Knight = (props: IconProps) => (
<Icon { ...props }>
<path id="knight" d="M26,26v2H5V26a2,2,0,0,1,2-2H24A2,2,0,0,1,26,26ZM9.9389,22H22c0-4-5.57825-5.67822-5.9624-10.38428l6.10382-.87207A.99983.99983,0,0,0,23,9.75378V8.31445a1.00005,1.00005,0,0,0-.64935-.93652L16,5V3.03809a8.799,8.799,0,0,0-7.94666,8.5747C8.05334,17,10,18,10,21,10,21.35547,9.96771,21.676,9.9389,22Z"/>
</Icon>
)

export default Knight;
10 changes: 7 additions & 3 deletions app/components/projects/ProjectItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CompanyLink from '@/app/components/career/CompanyLink';
import TechItem from '@/app/components/career/TechItem';
import TimeSpan from '@/app/components/career/TimeSpan';
import ArrowRight from '@/app/components/icons/ArrowRight';
import ProjectType from '@/app/components/projects/ProjectType';
import { ProjectData } from '@/models/project';

interface ProjectItemProps {
Expand All @@ -23,9 +24,12 @@ const ProjectItem = ({ item }: ProjectItemProps) => (
</Link>
</h4>
</header>
{ item.company ? <div className="font-thin mb-2">
<CompanyLink company={item.company} />
</div> : null }
{ item.company
? <div className="font-thin mb-2">
<ProjectType type={item.type} />
<CompanyLink company={item.company} />
</div>
: <ProjectType type={item.type} label /> }
{ item.description ? <p>{ item.description }</p> : null }
{ (!item.description && item.bullets?.length) ? (
<ul className="bullet-list">{
Expand Down
34 changes: 34 additions & 0 deletions app/components/projects/ProjectMasterData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

import CompanyLink from '@/app/components/career/CompanyLink';
import TechItem from '@/app/components/career/TechItem';
import TimeSpan from '@/app/components/career/TimeSpan';
import ProjectType from '@/app/components/projects/ProjectType';
import { ProjectData } from '@/models/project';

const ProjectMasterData = ({ project }: { project: ProjectData }) => (
<section id={project.slug}>
<h2>{ project.title }</h2>

<p className="mb-2">{ project.description }</p>

<p className="mb-2">
Zeitspanne: <TimeSpan startDate={project.startDate} endDate={project.endDate} />
</p>

<p className="mb-2">
Projektart: <ProjectType type={project.type} label />
</p>

{ project.company
? <p className="mb-2">Firma: <CompanyLink company={project.company} /></p>
: null }

<ul className="flex flex-wrap mt-3 gap-2">
{ (project.tech || []).map((t) => (
<TechItem key={t.slug} item={t} />
))}
</ul>
</section>
);

export default ProjectMasterData;
35 changes: 35 additions & 0 deletions app/components/projects/ProjectType.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Banknotes from '@/app/components/icons/Banknotes';
import BuildingsCity from '@/app/components/icons/BuildingsCity';
import HeartEmpty from '@/app/components/icons/HeartEmpty';
import Knight from '@/app/components/icons/Knight';
import { ProjectType } from '@/models/project';

export const projectTypeLabels = {
employee: 'Angestellter',
founder: 'Gründer',
freelance: 'Freiberuflich',
private: 'Privat',
volunteer: 'Ehrenamtlich',
};

const ProjectType = ({ type, label }: { type: ProjectType; label?: boolean }) => {
const TypeIcon = {
employee: BuildingsCity,
founder: HeartEmpty,
freelance: Banknotes,
private: Knight,
}[type];

if (!TypeIcon) {
return null;
}

return (
<>
<TypeIcon title={projectTypeLabels[type]} className="inline-block -mt-0.5 mr-2" />
{ label ? projectTypeLabels[type] : null }
</>
);
};

export default ProjectType;
4 changes: 2 additions & 2 deletions app/lebenslauf/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { Metadata } from 'next';
import CareerList from '@/app/components/career/CareerList';

export const metadata: Metadata = {
title: 'Lebenslauf',
title: 'Berufserfahrung',
};

const ResumePage = () => (
<div className="resume-page pt-4 lg:pt-10 lg:mr-80">
<section id="lebenslauf">
<h2>Lebenslauf</h2>
<h2>Berufserfahrung</h2>

<CareerList />
</section>
Expand Down
10 changes: 6 additions & 4 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { useEffect, useState } from 'react';
import LinkButton from './components/LinkButton';
import ArrowRight from './components/icons/ArrowRight';

const code = ['arrowup', 'arrowup', 'arrowdown', 'arrowdown', 'arrowleft', 'arrowright', 'arrowleft', 'arrowright', 'b', 'a'];

const NotFound = () => {
const code = ['arrowup', 'arrowup', 'arrowdown', 'arrowdown', 'arrowleft', 'arrowright', 'arrowleft', 'arrowright', 'b', 'a'];
const [index, setIndex] = useState(0);

useEffect(() => {
const onKeyDown = (e: KeyboardEvent) => {
if (['Shift', 'CapsLock'].includes(e.key)) {
Expand All @@ -29,7 +30,7 @@ const NotFound = () => {
return () => {
window.removeEventListener('keydown', onKeyDown);
};
}, [index, code]);
}, [index]);

return (
<div className="not-found-page pt-4 lg:pt-10 lg:mr-80">
Expand Down Expand Up @@ -83,7 +84,8 @@ const NotFound = () => {
{ 10 <= index
? <p className="mt-2">
<LinkButton
href={`mailto:manuel@schaechinger.com?subject=[${code.map((c, i) => c[index - (i + 1)]).reverse().join('')}] Anfrage`}
href={`mailto:manuel@schaechinger.com?subject=Projekt-Anfrage über Homepage [${
code.map((c, i) => c[index - (i + 1)]).reverse().join('')}]`}
label="Jetzt durchstarten"
/>
</p>
Expand Down
2 changes: 1 addition & 1 deletion app/projekte/[slug]/not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const ProjectNotFoundPage = (props: { params: { slug: string } }) => (
<h2>404 &ndash; Projekt nicht gefunden</h2>


<p className="mb-2">
<p className="mb-4">
Dieses Projekt existiert nicht oder ist nicht mehr verfgbar. Sehen Sie sich gerne meine
anderen Projekte an und finden Sie das passende.
</p>
Expand Down
26 changes: 3 additions & 23 deletions app/projekte/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import { Metadata } from 'next';
import Link from 'next/link';
import { notFound } from 'next/navigation';

import CompanyLink from '@/app/components/career/CompanyLink';
import TechItem from '@/app/components/career/TechItem';
import TimeSpan from '@/app/components/career/TimeSpan';
import LinkButton from '@/app/components/LinkButton';
import DetailBlock from '@/app/components/projects/DetailBlock';
import { getDatabase } from '@/app/lib/db/factory';
import LinkButton from '@/app/components/LinkButton';
import ProjectMasterData from '@/app/components/projects/ProjectMasterData';

interface ProjectPageProps {
params: {
Expand Down Expand Up @@ -41,25 +39,7 @@ const ProjectPage = async ({ params }: ProjectPageProps) => {

return (
<div className={`project-page page--${project.slug} pt-4 lg:pt-10`}>
<section id={project.slug}>
<h2>{ project.title }</h2>

<p className="mb-2">{ project.description }</p>

<p className="mb-2">
Zeitspanne: <TimeSpan startDate={project.startDate} endDate={project.endDate} />
</p>

{ project.company
? <p className="mb-2">Firma: <CompanyLink company={project.company} /></p>
: null }

<ul className="flex flex-wrap mt-3 gap-2">
{ (project.tech || []).map((t) => (
<TechItem key={t.slug} item={t} />
))}
</ul>
</section>
<ProjectMasterData project={project} />

{ project.details?.requirements
? <DetailBlock id="anforderungen" title="Anforderungen" content={project.details.requirements} />
Expand Down
Loading

0 comments on commit c97abb0

Please sign in to comment.