diff --git a/keith-portfolio/PRD.md b/keith-portfolio/PRD.md index fe5cba5..a09db17 100644 --- a/keith-portfolio/PRD.md +++ b/keith-portfolio/PRD.md @@ -36,6 +36,7 @@ Phase 1 has no forms, no logins, no secrets, so risk is low. External links use ## Phase 1 status (done) - Content comes from Keith's existing portfolio: profile, 8 capabilities, 3 roles + 5 earlier roles, 4 projects, 10 certifications, contact details (all in `src/data/content.ts`). +- Each project card has its own illustrative diagram (drawn from the deliverables in Keith's portfolio text; swap for real screenshots when available). - Sections: Hero (portrait), scrolling photo/skills rows, About, Capability, Experience, Projects (stacking cards), Credentials, Contact. - Photos and the Kanit font ship inside the site (no outside image hosts needed). - Tested at 360, 390, 768, 1024, 1440 and 1920 px wide: no sideways scroll, no console errors, all images load. diff --git a/keith-portfolio/src/components/ProjectDiagram.tsx b/keith-portfolio/src/components/ProjectDiagram.tsx new file mode 100644 index 0000000..3b73c3a --- /dev/null +++ b/keith-portfolio/src/components/ProjectDiagram.tsx @@ -0,0 +1,149 @@ +import type { CSSProperties, ReactNode } from 'react'; + +export type DiagramKind = 'network' | 'server' | 'sccm' | 'voice'; + +const INK = '#D7E2EA'; +const TEAL = '#2BB3A6'; +const MUTED = 'rgba(215,226,234,0.55)'; +const FILL = '#14161a'; + +function Box({ x, y, w, h, label, sub, accent }: { x: number; y: number; w: number; h: number; label: string; sub?: string; accent?: boolean }) { + return ( + + + {label} + {sub && {sub}} + + ); +} + +function Line({ x1, y1, x2, y2, dashed }: { x1: number; y1: number; x2: number; y2: number; dashed?: boolean }) { + return ; +} + +function Arrow({ x1, y, x2, label }: { x1: number; y: number; x2: number; label?: string }) { + return ( + + + + {label && {label}} + + ); +} + +function Dot({ cx, cy, r = 14 }: { cx: number; cy: number; r?: number }) { + return ; +} + +function Wifi({ cx, cy }: { cx: number; cy: number }) { + return ( + + + + + + ); +} + +const diagrams: Record = { + network: { + label: 'Network topology: Fortinet firewall connects to Fortinet 48P switches, which connect to access points.', + body: ( + <> + + + + + + + + {[90, 210, 390, 510].map((x, i) => ( + + + + + + ))} + Access point uplift + Network topology upgrade + + ), + }, + server: { + label: 'Server upgrade: virtual machines and services move from the existing server to the upgraded server, with updated network settings.', + body: ( + <> + + Existing server + + + + + Upgraded server + + + + + + + ), + }, + sccm: { + label: 'SCCM implementation: install and configure SCCM, prepare settings, then establish the task-sequence process for endpoints.', + body: ( + <> + + + + + + + + + + {[150, 250, 350, 450].map((x) => ( + + + + + + ))} + Endpoints built through the task sequence + + ), + }, + voice: { + label: 'Microsoft Teams calling: number porting, dial-plan and call-flow design, then users supported by training, documentation and adoption monitoring.', + body: ( + <> + + + + + + + + {[100, 300, 500].map((x) => ( + + + + + + ))} + User training + Documentation + Adoption monitoring + Microsoft Teams calling + + ), + }, +}; + +export default function ProjectDiagram({ kind, className, style }: { kind: DiagramKind; className?: string; style?: CSSProperties }) { + const d = diagrams[kind]; + return ( + + {d.body} + + ); +} diff --git a/keith-portfolio/src/data/content.ts b/keith-portfolio/src/data/content.ts index afb4950..3feff10 100644 --- a/keith-portfolio/src/data/content.ts +++ b/keith-portfolio/src/data/content.ts @@ -3,6 +3,8 @@ import leadership from '../assets/leadership.webp'; import systems from '../assets/systems.webp'; import signalMark from '../assets/signal-mark.webp'; +import type { DiagramKind } from '../components/ProjectDiagram'; + export const images = { portrait, leadership, systems, signalMark }; export const profile = { @@ -85,32 +87,36 @@ export const projects = [ name: 'Network project', body: 'Fortinet Firewall upgrade, Fortinet 48P Switches upgrade, Fortinet access point uplift, and network topology upgrade.', delivered: ['Fortinet firewall upgrade', 'Fortinet 48P switches upgrade', 'Fortinet access point uplift', 'Network topology upgrade'], - images: [systems, leadership] as [string, string], - position: ['center', 'center'] as [string, string], + diagram: 'network' as DiagramKind, + photo: systems, + photoPosition: 'center', }, { category: 'Infrastructure', name: 'Server upgrade', body: 'Upgraded the server with existing VMs and services, migrated data, and configured updated network settings.', delivered: ['Server upgraded with existing VMs and services', 'Data migrated', 'Updated network settings configured'], - images: [leadership, systems] as [string, string], - position: ['70% 40%', '20% 60%'] as [string, string], + diagram: 'server' as DiagramKind, + photo: leadership, + photoPosition: '70% 40%', }, { category: 'Endpoint', name: 'SCCM implementation', body: 'Installed and configured SCCM, prepared the required settings, and established the task-sequence process.', delivered: ['SCCM installed and configured', 'Required settings prepared', 'Task-sequence process established'], - images: [systems, leadership] as [string, string], - position: ['80% 20%', '30% 70%'] as [string, string], + diagram: 'sccm' as DiagramKind, + photo: systems, + photoPosition: '80% 20%', }, { category: 'Voice', name: 'Microsoft Teams calling', body: 'Delivered number-porting support, call-flow and dial-plan design, user training, documentation, and adoption monitoring.', delivered: ['Number-porting support', 'Call-flow and dial-plan design', 'User training and documentation', 'Adoption monitoring'], - images: [leadership, systems] as [string, string], - position: ['50% 80%', '60% 30%'] as [string, string], + diagram: 'voice' as DiagramKind, + photo: leadership, + photoPosition: '50% 80%', }, ]; diff --git a/keith-portfolio/src/sections/ProjectsSection.tsx b/keith-portfolio/src/sections/ProjectsSection.tsx index 6d4e798..9d6b7f4 100644 --- a/keith-portfolio/src/sections/ProjectsSection.tsx +++ b/keith-portfolio/src/sections/ProjectsSection.tsx @@ -2,6 +2,7 @@ import { useRef } from 'react'; import { motion, useScroll, useTransform } from 'framer-motion'; import { Check } from 'lucide-react'; import FadeIn from '../components/FadeIn'; +import ProjectDiagram from '../components/ProjectDiagram'; import { projects } from '../data/content'; type Project = (typeof projects)[number]; @@ -34,21 +35,35 @@ function ProjectCard({ project, index, total }: { project: Project; index: numbe {project.body}

-
-
- - +
+
+ +
+ Delivered +
    + {project.delivered.map((d) => ( +
  • + + {d} +
  • + ))} +
+
-
- Delivered -
    - {project.delivered.map((d) => ( -
  • - - {d} -
  • - ))} -
+
+