diff --git a/frontend/public/templates/MySpace_2005.png b/frontend/public/templates/MySpace_2005.png new file mode 100644 index 000000000..e74e0ad0b Binary files /dev/null and b/frontend/public/templates/MySpace_2005.png differ diff --git a/frontend/src/components/portfolio/templates/MySpace_2005/index.jsx b/frontend/src/components/portfolio/templates/MySpace_2005/index.jsx new file mode 100644 index 000000000..2e4f8952f --- /dev/null +++ b/frontend/src/components/portfolio/templates/MySpace_2005/index.jsx @@ -0,0 +1,952 @@ +import React, { useState, useEffect, useMemo } from "react"; +import { + Github, Linkedin, Twitter, Mail, Globe, ExternalLink, + MapPin, Briefcase, Code, Star, Users, Eye, Heart, + MessageSquare, UserPlus, Bookmark, + Award, GraduationCap, +} from "lucide-react"; +import { usePortfolio } from "../../../../context/PortfolioContext"; + +/* ═══════════════════════════════════════════════════════════════ + MYSPACE 2005 PORTFOLIO TEMPLATE — AUTHENTIC MICRO-INTERACTIONS + ─────────────────────────────────────────────────────────────── + Full viewport-width edge-to-edge layout, persistent 3-column + desktop grid (~23% Left, ~52% Center, ~25% Right). Period-accurate + 2005 micro-interactions: profile image hover, Windows XP pressed + buttons, classic link hovers, single-active project accordion + (▶ / ▼), sequential comment reveal, animated skill bars (0 -> N%), + gentle page fade-in, and native cursor behavior. + ═══════════════════════════════════════════════════════════════ */ + +const MS = { + navBg: "#003399", + navBgDark: "#001a66", + navText: "#ffffff", + navLink: "#99ccff", + pageBg: "#c0d4e8", + contentBg: "#ffffff", + sectionHeader: "#003366", + sectionHeaderTx: "#ffffff", + border: "#b0b0b0", + borderLight: "#cccccc", + text: "#000000", + textMuted: "#444444", + link: "#003399", + linkHover: "#0000aa", + profileBg: "#dde9f4", + tableBg: "#c8dced", + tableAlt: "#e8eff6", + contactBg: "#eef3f9", + orange: "#ff6600", + font: "Verdana, Arial, Helvetica, sans-serif", +}; + +const THEME_CSS = ` + .ms05 *, .ms05 *::before, .ms05 *::after { box-sizing: border-box; } + + /* Requirement 9: Page Load Fade In (0.97 -> 1, 180ms) */ + @keyframes ms05fadeIn { + from { opacity: 0.97; } + to { opacity: 1; } + } + + .ms05 { + font-family: ${MS.font}; + font-size: 12px; + line-height: 1.5; + color: ${MS.text}; + background: ${MS.pageBg}; + min-height: 100vh; + margin: 0; + padding: 0; + width: 100%; + -webkit-font-smoothing: auto; + animation: ms05fadeIn 180ms ease-out forwards; + cursor: url('data:image/svg+xml;utf8,'), default; + } + + /* Requirement 7 & 10: Classic Hyperlink Hover & Pointer Cursor */ + .ms05 a, .ms05-link-action { + color: ${MS.link}; + text-decoration: underline; + cursor: pointer; + transition: color 120ms ease; + } + .ms05 a:hover, .ms05-link-action:hover { + color: ${MS.linkHover} !important; + text-decoration: underline !important; + } + + /* Native I-beam cursor for selectable text */ + .ms05 p, .ms05 td, .ms05 th { + cursor: text; + } + .ms05 img { max-width: 100%; height: auto; } + + /* Blink for online status dot */ + @keyframes ms05blink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.3; } + } + .ms05-blink { animation: ms05blink 1.8s ease-in-out infinite; } + + /* Requirement 1: Profile Avatar Hover (border darkens + subtle brightness increase, NO scale/lift) */ + .ms05-avatar-box { + border: 1px solid ${MS.border}; + padding: 3px; + background: #ffffff; + transition: border-color 150ms ease, filter 150ms ease; + cursor: pointer; + } + .ms05-avatar-box:hover { + border-color: ${MS.sectionHeader} !important; + filter: brightness(1.05); + } + + /* Requirement 2: Classic Windows XP / HTML Button Interaction */ + .ms05-btn { + background: ${MS.contactBg}; + border: 1px solid ${MS.border}; + padding: 4px 7px; + font-size: 11px; + font-family: ${MS.font}; + display: flex; + align-items: center; + gap: 4px; + color: ${MS.link}; + flex: 1 1 47%; + min-width: 0; + justify-content: center; + cursor: pointer; + user-select: none; + transition: background 120ms ease, border-color 120ms ease, transform 60ms ease, box-shadow 60ms ease; + } + .ms05-btn:hover { + background: #e4edf6 !important; + border-color: #777777 !important; + color: ${MS.link} !important; + } + .ms05-btn:active { + transform: translateY(1px); + border-color: #555555 !important; + box-shadow: inset 1px 1px 2px rgba(0, 0, 0, 0.2); + } + + /* Requirement 3: Navigation Link Hover (underline + lighter text, 120ms) */ + .ms05-nav-link { + color: ${MS.navLink}; + font-size: 12px; + font-family: ${MS.font}; + text-decoration: none; + cursor: pointer; + transition: color 120ms ease; + } + .ms05-nav-link:hover { + color: #ffffff !important; + text-decoration: underline !important; + } + + /* Requirement 5: Sequential Comment Appearance on Load */ + @keyframes ms05commentReveal { + from { opacity: 0.35; transform: translateY(1px); } + to { opacity: 1; transform: translateY(0); } + } + .ms05-comment { + animation: ms05commentReveal 160ms ease-out forwards; + transition: background 120ms ease; + } + .ms05-comment:hover { + background: #f0f5fa !important; + } + + /* Requirement 6: Friend Card Hover */ + .ms05-friend-card { + text-align: center; + cursor: pointer; + transition: filter 150ms ease; + } + .ms05-friend-card:hover img, + .ms05-friend-card:hover .ms05-friend-fallback { + border-color: ${MS.sectionHeader} !important; + filter: brightness(1.06); + } + .ms05-friend-card:hover .ms05-friend-name { + color: ${MS.linkHover} !important; + text-decoration: underline !important; + } + + /* Social link row states */ + .ms05-social { + color: ${MS.link}; + text-decoration: underline; + cursor: pointer; + transition: background 120ms ease, color 120ms ease, border-color 120ms ease; + } + .ms05-social:hover { + background: #f5f9ff !important; + color: ${MS.linkHover} !important; + text-decoration: underline !important; + } + .ms05-social:active { + background: #e6f0fa !important; + border-color: #999999 !important; + color: ${MS.linkHover} !important; + } + + /* Hover effect for project items */ + .ms05-project-item { + transition: background 120ms ease; + } + .ms05-project-item:hover { + background: #f4f8fc !important; + } + + /* Requirement 8: Skill bar fill animation */ + .ms05-skill-bar-fill { + transition: width 500ms linear; + } + + /* 3-Column Desktop Proportions with Dominant Center Column */ + .ms05-layout { + display: flex; + gap: 10px; + width: 100%; + align-items: flex-start; + } + .ms05-col-left { + flex: 0 0 23%; + min-width: 210px; + } + .ms05-col-center { + flex: 1 1 52%; + min-width: 0; + } + .ms05-col-right { + flex: 0 0 25%; + min-width: 230px; + } + + /* Respect prefers-reduced-motion */ + @media (prefers-reduced-motion: reduce) { + .ms05 { animation: none !important; } + .ms05-comment { animation: none !important; } + .ms05-skill-bar-fill { transition: none !important; } + .ms05-btn:active { transform: none !important; } + } + + /* Responsive Stacking below 1024px */ + @media (max-width: 1023px) { + .ms05-layout { + flex-direction: column !important; + } + .ms05-col-left, + .ms05-col-center, + .ms05-col-right { + width: 100% !important; + flex: 1 1 100% !important; + min-width: 100% !important; + } + } +`; + +/* ─── Section Header ─── */ +function Header({ children, icon, style = {} }) { + return ( +
+ {icon} + {children} +
+ ); +} + +/* ─── Box: a bordered white panel with consistent breathing room ─── */ +function Box({ children, nopad, style = {} }) { + return ( +
+ {nopad ? children :
{children}
} +
+ ); +} + +/* ═══════════════════════════════════════════════════════════════ + FULL-WIDTH NAV BAR + ═══════════════════════════════════════════════════════════════ */ +function NavBar({ name }) { + const navItems = ["Home", "Browse", "Search", "Invite", "Mail", "Blogs", "Favorites", "Forum", "Groups", "Music", "Video"]; + return ( + + ); +} + +/* ═══════════════════════════════════════════════════════════════ + LEFT SIDEBAR MODULES + ═══════════════════════════════════════════════════════════════ */ +function ProfileCard({ personal, socials }) { + return ( + +
{personal.name || "User"}
+
+ {/* Requirement 1: Profile Avatar Hover */} + {personal.avatar && ( +
+ {`${personal.name}'s +
+ )} + + {/* Online status indicator */} +
+
+ + {/* Headline */} +
+ "{personal.title || "Developer"}" +
+ {personal.tagline && ( +
+ ♪ Mood: {personal.tagline} +
+ )} + + {/* Details Table */} + + + {[ + personal.location && { label: "Location", value: <>{personal.location} }, + socials.email && { label: "Email", value: {socials.email} }, + { label: "Member Since", value: "2005" }, + { label: "Profile Views", value: "14,923" }, + { label: "Last Login", value: "Today" }, + ].filter(Boolean).map((row, i) => ( + + + + + ))} + +
{row.label}:{row.value}
+
+
+ ); +} + +/* Requirement 2: Classic Windows XP / HTML Button Interaction */ +function ContactBox({ name }) { + const buttons = [ + { icon: , label: "Send Message" }, + { icon: , label: "Add to Friends" }, + { icon: , label: "Instant Message" }, + { icon: , label: "Add Favorites" }, + { icon: , label: "Add to Group" }, + { icon: , label: "Block User" }, + ]; + + return ( + +
}>Contacting {(name || "User").split(" ")[0]}
+
+ {buttons.map((btn) => ( + + ))} +
+
+ ); +} + +function UrlRow({ name }) { + return ( + +
+ URL: + + myspace.com/{(name || "user").toLowerCase().replace(/\s+/g, "")} + +
+
+ ); +} + +/* Requirement 6: Friend Card Hover */ +function TopFriends({ testimonials }) { + if (!testimonials || testimonials.length === 0) return null; + return ( + +
}>{`${(testimonials || []).length} Top Friends`}
+
+ {testimonials.slice(0, 8).map((t, i) => ( +
+ {t.avatar ? ( + {t.name + ) : ( + + )} +
+ {t.name || t.author} +
+
+ ))} +
+
+ ); +} + +/* Requirement 8: Skill Bar Fill Animation (0% to value on initial mount) */ +function Skills({ skills }) { + const [animated, setAnimated] = useState(false); + + useEffect(() => { + const timer = setTimeout(() => setAnimated(true), 50); + return () => clearTimeout(timer); + }, []); + + const categories = useMemo(() => { + if (!skills || skills.length === 0) return {}; + const cats = {}; + skills.forEach((s) => { + const cat = s.category || "General"; + if (!cats[cat]) cats[cat] = []; + cats[cat].push(s); + }); + return cats; + }, [skills]); + + if (!skills || skills.length === 0) return null; + + return ( + +
}>My Skills
+
+ {Object.entries(categories).map(([cat, catSkills]) => ( +
+
+ ▸ {cat} +
+ {catSkills.map((skill, i) => ( +
+ {skill.name} +
+ {/* Thin sharp rectangular progress bar */} +
+
+
+ {skill.level}% +
+
+ ))} +
+ ))} +
+ + ); +} + +/* ═══════════════════════════════════════════════════════════════ + CENTER COLUMN MODULES — PRIMARY VISUAL FOCUS (About, Projects, Experience) + ═══════════════════════════════════════════════════════════════ */ +function AboutMe({ personal }) { + if (!personal.bio) return null; + return ( + +
}>About Me
+
+

{personal.bio}

+
+
+ ); +} + +/* Requirement 4: Authentic Project Accordion (▶ Collapsed / ▼ Expanded) */ +function Projects({ projects }) { + const [expanded, setExpanded] = useState(null); + + if (!projects || projects.length === 0) return null; + + return ( + +
}>My Projects
+
+ {projects.map((p, i) => { + const isExpanded = expanded === i; + return ( +
+
+ {/* Scaled Dominant Preview Image */} + {p.image && ( + {p.title} + )} +
+ {/* Accordion Toggle Title */} +
+ +
+

+ {p.description} +

+ {/* Tech Tags */} + {p.techStack?.length > 0 && ( +
+ Tech: + {p.techStack.map((t) => ( + + {t} + + ))} +
+ )} + {/* Requirement 7: Action Links */} +
+ {p.liveUrl && ( + + Live Demo + + )} + {p.githubUrl && ( + + Source Code + + )} +
+
+
+
+ ); + })} +
+
+ ); +} + +function Experience({ experience }) { + if (!experience || experience.length === 0) return null; + return ( + +
}>Experience
+
+ {experience.map((exp, i) => ( +
+
+ {exp.role || exp.title} + + {exp.duration || exp.period || `${exp.startDate || ""} – ${exp.endDate || ""}`} + +
+
{exp.company}
+

{exp.description}

+
+ ))} +
+
+ ); +} + +/* ═══════════════════════════════════════════════════════════════ + RIGHT SIDEBAR MODULES (Stats, Socials, Education/Certifications, Comments) + ═══════════════════════════════════════════════════════════════ */ +function Stats({ stats, skills, projects, experience }) { + const rows = useMemo(() => { + const r = []; + if (stats?.yearsExperience != null) r.push({ icon: , label: "Years Experience", value: stats.yearsExperience }); + if (stats?.projectsCompleted != null) r.push({ icon: , label: "Projects Completed", value: stats.projectsCompleted }); + else if (projects?.length) r.push({ icon: , label: "Total Projects", value: projects.length }); + if (stats?.happyClients != null) r.push({ icon: , label: "Happy Clients", value: stats.happyClients }); + if (skills?.length) r.push({ icon: , label: "Skills Count", value: skills.length }); + if (experience?.length) r.push({ icon: , label: "Roles Held", value: experience.length }); + return r; + }, [stats, skills, projects, experience]); + + if (rows.length === 0) return null; + + return ( + +
}>Profile Stats
+ + + {rows.map((row, i) => ( + + + + + ))} + +
+ {row.icon} {row.label} + + {row.value} +
+
+ ); +} + +function Socials({ socials }) { + const links = useMemo(() => { + const r = []; + if (socials.github) r.push({ icon: , label: "GitHub", href: socials.github }); + if (socials.linkedin) r.push({ icon: , label: "LinkedIn", href: socials.linkedin }); + if (socials.twitter) r.push({ icon: , label: "Twitter / X", href: socials.twitter }); + if (socials.email) r.push({ icon: , label: "Email", href: socials.email.includes("@") ? `mailto:${socials.email}` : socials.email }); + if (socials.website || socials.portfolio) r.push({ icon: , label: "Website", href: socials.website || socials.portfolio }); + return r; + }, [socials]); + + if (links.length === 0) return null; + + return ( + +
}>My Social Links
+
+ {links.map((link, i) => ( + + {link.icon} + {link.label} + + + ))} +
+
+ ); +} + +function DynamicEducation({ education }) { + if (!Array.isArray(education) || education.length === 0) return null; + return ( + +
}>Education
+
+ {education.map((edu, i) => ( +
+
{edu.degree || edu.institution}
+ {edu.degree && edu.institution &&
{edu.institution}
} + {edu.year &&
{edu.year}
} +
+ ))} +
+
+ ); +} + +function DynamicCertifications({ certifications }) { + if (!Array.isArray(certifications) || certifications.length === 0) return null; + return ( + +
}>Certifications
+
+ {certifications.map((cert, i) => ( +
+
{cert.name}
+ {cert.issuer &&
{cert.issuer}
} + {cert.year &&
{cert.year}
} +
+ ))} +
+
+ ); +} + +/* Requirement 5: Sequential Comment Appearance (50-80ms delay) */ +function Comments({ testimonials, name }) { + if (!testimonials || testimonials.length === 0) return null; + + return ( + +
}> + {`${name || "User"}'s Comments`} +
+
+ Displaying {testimonials.length} of {testimonials.length} comments +
+
+ {testimonials.map((t, i) => ( +
+ {/* Avatar — Enriched 58px size */} +
+ {t.avatar ? ( + {t.name + ) : ( + + )} +
+ {t.name || t.author} +
+
+ + {/* Comment body */} +
+
+ {t.name || t.author} + {t.role && — {t.role}} +
+

+ “{t.text || t.content}” +

+
+ {i === 0 ? "2 hours ago" : i === 1 ? "yesterday" : `${i + 1} days ago`} + {" · "} + Reply +
+
+
+ ))} +
+
+ ); +} + +/* ═══════════════════════════════════════════════════════════════ + FULL-WIDTH FOOTER + ═══════════════════════════════════════════════════════════════ */ +function Footer() { + return ( +
+ ©2005 MySpaceDev Inc. All Rights Reserved.{" "} + Privacy Policy |{" "} + Terms of Service |{" "} + Safety Tips |{" "} + Contact MySpace |{" "} + Promote! |{" "} + Advertise +
+ ); +} + +/* ═══════════════════════════════════════════════════════════════ + MAIN TEMPLATE COMPONENT + ═══════════════════════════════════════════════════════════════ */ +export default function Template() { + const { portfolioData } = usePortfolio(); + const { + personal = {}, + socials = {}, + stats = {}, + skills = [], + projects = [], + experience = [], + testimonials = [], + education = [], + certifications = [], + } = portfolioData || {}; + + return ( +
+ + + {/* Full-width edge-to-edge NavBar */} + + + {/* Full-width Profile Sub-header Banner with Breadcrumb & View My Links */} +
+
+ {/* Refined Breadcrumb */} +
+ MySpace.com + > + {personal.name || "User"} + {personal.title && ({personal.title})} +
+ {/* Refined View My Bar */} +
+ View My: + {["Photos", "Videos", "Blogs", "Friends", "Favorites"].map((item, i) => ( + + {i > 0 && |} + {item} + + ))} +
+
+
+ + {/* ── PERSISTENT 3-COLUMN DESKTOP LAYOUT (Full-width edge-to-edge canvas) ── */} +
+
+ + {/* ── LEFT SIDEBAR (~23%) ── */} +
+ + + + + +
+ + {/* ── MAIN CENTER COLUMN (~52%) — LOGICAL FLOW: About → Projects → Experience ── */} +
+ + + +
+ + {/* ── RIGHT SIDEBAR (~25%) ── */} +
+ + + + + +
+ +
+
+ + {/* Full-width Footer */} +
+ ); +} diff --git a/frontend/src/data/templates.js b/frontend/src/data/templates.js index 1abf2cf49..74cc381e4 100644 --- a/frontend/src/data/templates.js +++ b/frontend/src/data/templates.js @@ -1,11 +1,25 @@ export const templates = [ -{ + { + id: "MySpace_2005", + title: "MySpace 2005", + category: "Portfolio", + colorScheme: "Light", + layout: "Grid", + author: "Ayush Srivastava", + views: 0, + rating: 5.0, + image: "/templates/MySpace_2005.png", + createdAt: "2026-07-17", + isComplete: true, + description: "A faithful recreation of a classic 2005 MySpace profile page as a developer portfolio. Features the iconic two-column layout, blue navigation, connected white panels, dark blue section headers, compact Verdana typography, interactive project accordion, and stacked profile modules — pure nostalgia." + }, + { id: "Macintosh_1984_Classic", title: "Macintosh 1984 Classic", category: "Portfolio", colorScheme: "Light", layout: "Interactive", - author: "Antigravity", + author: "Ayush Srivastava", views: 0, rating: 5.0, image: "/templates/Macintosh_1984_Classic.png", @@ -13,7 +27,7 @@ export const templates = [ isComplete: true, description: "A pixel-perfect recreation of the original 1984 Macintosh desktop as a fully interactive portfolio. Features authentic Finder windows, Chicago-inspired bitmap typography, double-click desktop icons, and classic monochrome aesthetics." }, -{ + { id: "Hot_Air_Balloon_Drifting", title: "Hot Air Balloon Drifting", @@ -56,7 +70,7 @@ export const templates = [ isComplete: true, description: "A premium, interactive developer portfolio styled like a modern dating application. Swipe through projects, chat history experience, and match with the developer." }, - { + { "id": "Rubik_s_Cube_3D_Rotate", "title": "Rubik's Cube 3D Rotate", "category": "Portfolio", @@ -68,7 +82,7 @@ export const templates = [ "image": "/template-previews/Rubik_s_Cube_3D_Rotate.png", "createdAt": "2026-06-24", isComplete: true -}, + }, { id: "Jigsaw_Puzzle_Assembly", title: "Jigsaw Puzzle Assembly", @@ -83,7 +97,7 @@ export const templates = [ description: "A vibrant portfolio where big jigsaw pieces are assembled in the hero and scatter as you scroll down — rejoining as you scroll back up. Funky neon colours, unique interlocking shapes, and scroll-driven physics.", isComplete: true }, - + { "id": "Live_Satellite_Imagery_Feed", "title": "Live Satellite Imagery Feed",