Skip to content

Commit

Permalink
Added categories to skills
Browse files Browse the repository at this point in the history
  • Loading branch information
santosh898 committed Nov 28, 2024
1 parent 506ce6c commit 6108319
Showing 1 changed file with 130 additions and 31 deletions.
161 changes: 130 additions & 31 deletions src/components/Skills.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { Card, CardContent } from "@/components/ui/card";

// Import SVGs
import ReactLogo from "@/logos/react.svg";
import ReactNativeLogo from "@/logos/react-native.svg";
import JavascriptLogo from "@/logos/javascript.svg";
Expand All @@ -22,41 +23,139 @@ import WebextensionsLogo from "@/logos/webextensions.svg";
import WebrtcLogo from "@/logos/webrtc.svg";
import ThingsboardLogo from "@/logos/thingsboard.svg";
import DockerLogo from "@/logos/docker.svg";
import { Button } from "./ui/button";
import { ChevronDown, ChevronUp } from "lucide-react";
import { useEffect, useState } from "react";

const seggregatedSkills = {
frontend: [
{ name: "React", logo: ReactLogo },
{ name: "React Native", logo: ReactNativeLogo },
{ name: "Javascript", logo: JavascriptLogo },
{ name: "Typescript", logo: TypescriptLogo },
{ name: "Styled Components", logo: StyledComponentsLogo },
{ name: "Tailwind", logo: TailwindLogo },
{ name: "Vue.JS", logo: VuejsLogo },
{ name: "Solid.JS", logo: SolidjsLogo },
{ name: "Redux", logo: ReduxLogo },
{ name: "Next.JS", logo: NextjsLogo },
{ name: "Vitest/Jest", logo: VitestLogo },
],
backend: [
{ name: "Node.JS", logo: NodejsLogo },
{ name: "Postgres", logo: PostgresqlLogo },
{ name: "GraphQL", logo: GraphqlLogo },
{ name: "Firebase", logo: FirebaseLogo },
{ name: "Microservices", logo: MicroservicesLogo },
{ name: "Docker", logo: DockerLogo },
],
misc: [
{ name: "Electron.JS", logo: ElectronLogo },
{ name: "Web Extensions", logo: WebextensionsLogo },
{ name: "WebRTC", logo: WebrtcLogo },
{ name: "Thingsboard", logo: ThingsboardLogo },
],
};

const ITEMS_TO_SHOW = 4;

function SkillSection({
title,
skills,
expanded,
onToggle,
}: {
title: string;
skills: typeof seggregatedSkills.frontend;
expanded: boolean;
onToggle: () => void;
}) {
const [isMobile, setIsMobile] = useState(false);

useEffect(() => {
const checkMobile = () => setIsMobile(window.innerWidth < 1024);
checkMobile();
window.addEventListener("resize", checkMobile);
return () => window.removeEventListener("resize", checkMobile);
}, []);

const skills = [
{ name: "React", logo: ReactLogo },
{ name: "React Native", logo: ReactNativeLogo },
{ name: "Javascript", logo: JavascriptLogo },
{ name: "Typescript", logo: TypescriptLogo },
{ name: "Node.JS", logo: NodejsLogo },
{ name: "Electron.JS", logo: ElectronLogo },
{ name: "Styled Components", logo: StyledComponentsLogo },
{ name: "Tailwind", logo: TailwindLogo },
{ name: "Postgres", logo: PostgresqlLogo },
{ name: "GraphQL", logo: GraphqlLogo },
{ name: "Vue.JS", logo: VuejsLogo },
{ name: "Solid.JS", logo: SolidjsLogo },
{ name: "Firebase", logo: FirebaseLogo },
{ name: "Microservices", logo: MicroservicesLogo },
{ name: "Redux", logo: ReduxLogo },
{ name: "Vitest/Jest", logo: VitestLogo },
{ name: "Next.JS", logo: NextjsLogo },
{ name: "Web Extensions", logo: WebextensionsLogo },
{ name: "WebRTC", logo: WebrtcLogo },
{ name: "Thingsboard", logo: ThingsboardLogo },
{ name: "Docker", logo: DockerLogo },
];
const displayedSkills = !isMobile
? skills
: expanded
? skills
: skills.slice(0, ITEMS_TO_SHOW);
const showToggle = skills.length > ITEMS_TO_SHOW && isMobile;

return (
<div className="flex-1 min-w-[250px]">
<h3 className="text-xl font-semibold mb-4 capitalize text-gray-100">
{title}
</h3>
<div className="space-y-2">
{displayedSkills.map((skill) => (
<Card
key={skill.name}
className="bg-gray-900 border-gray-800 text-gray-100"
>
<CardContent className="flex items-center gap-3 p-3">
<skill.logo className="h-8 w-8 mr-2 fill-current text-white" />
<span className="text-base font-medium">{skill.name}</span>
</CardContent>
</Card>
))}
{showToggle && (
<Button
variant="ghost"
className="w-full mt-2 text-gray-400"
onClick={onToggle}
>
{expanded ? (
<span className="flex items-center">
Show Less <ChevronUp className="ml-2 h-4 w-4" />
</span>
) : (
<span className="flex items-center">
Show More <ChevronDown className="ml-2 h-4 w-4" />
</span>
)}
</Button>
)}
</div>
</div>
);
}

const Skills = () => {
const [expandedSections, setExpandedSections] = useState<
Record<string, boolean>
>({
frontend: false,
backend: false,
misc: false,
});

const toggleSection = (section: string) => {
setExpandedSections((prev) => ({
...prev,
[section]: !prev[section],
}));
};

return (
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{skills.map((skill, index) => (
<Card key={index} className="bg-gray-900 border-gray-800 text-gray-100">
<CardContent className="flex items-center justify-center p-6">
<skill.logo className="h-8 w-8 mr-2 fill-current text-white" />
<span className="text-lg font-medium">{skill.name}</span>
</CardContent>
</Card>
{(
Object.entries(seggregatedSkills) as [
keyof typeof seggregatedSkills,
typeof seggregatedSkills.frontend
][]
).map(([category, skills]) => (
<SkillSection
key={category}
title={category}
skills={skills}
expanded={expandedSections[category]}
onToggle={() => toggleSection(category)}
/>
))}
</div>
);
Expand Down

0 comments on commit 6108319

Please sign in to comment.