🎨 refactor(pages): rearrange imports and formatting for Blog, BlogArticle, ProjectDetails, and Projects
This commit organizes import statements and standardizes code formatting across the Blog, BlogArticle, ProjectDetails, and Projects pages. Improvements include consistent spacing, use of double quotes, and more readable conditional rendering, contributing to better maintainability and readability of the codebase.
This commit is contained in:
+36
-32
@@ -1,15 +1,19 @@
|
|||||||
import { useState } from 'react';
|
import PageTransition from "@/components/PageTransition";
|
||||||
import { motion } from 'framer-motion';
|
import { Button } from "@/components/ui/button";
|
||||||
import { ArrowLeft, Calendar, Clock, User, Search } from 'lucide-react';
|
import { Input } from "@/components/ui/input";
|
||||||
import { Link } from 'react-router-dom';
|
import { motion } from "framer-motion";
|
||||||
import { Button } from '@/components/ui/button';
|
import { ArrowLeft, Calendar, Clock, Search, User } from "lucide-react";
|
||||||
import { Input } from '@/components/ui/input';
|
import { useState } from "react";
|
||||||
import Navbar from '@/components/Navbar';
|
import { Link } from "react-router-dom";
|
||||||
import Footer from '@/components/Footer';
|
import { useBlogs } from "./../hooks/queires/useBlogs";
|
||||||
import PageTransition from '@/components/PageTransition';
|
|
||||||
import { useBlogs } from './../hooks/queires/useBlogs';
|
|
||||||
|
|
||||||
const categories = ['All', 'AI & Machine Learning', 'Cloud Solutions', 'Web Development', 'Mobile Development'];
|
const categories = [
|
||||||
|
"All",
|
||||||
|
"AI & Machine Learning",
|
||||||
|
"Cloud Solutions",
|
||||||
|
"Web Development",
|
||||||
|
"Mobile Development",
|
||||||
|
];
|
||||||
|
|
||||||
const containerVariants = {
|
const containerVariants = {
|
||||||
hidden: { opacity: 0 },
|
hidden: { opacity: 0 },
|
||||||
@@ -24,23 +28,22 @@ const itemVariants = {
|
|||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
transition: { duration: 0.5, ease: 'easeOut' as const },
|
transition: { duration: 0.5, ease: "easeOut" as const },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Blog() {
|
export default function Blog() {
|
||||||
|
const { data } = useBlogs();
|
||||||
const {data} = useBlogs();
|
|
||||||
const blogPosts = data?.data.result;
|
const blogPosts = data?.data.result;
|
||||||
|
|
||||||
|
|
||||||
|
const [activeCategory, setActiveCategory] = useState("All");
|
||||||
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
|
|
||||||
const [activeCategory, setActiveCategory] = useState('All');
|
const filteredPosts = blogPosts?.filter((post) => {
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const matchesCategory =
|
||||||
|
activeCategory === "All" || post.category === activeCategory;
|
||||||
const filteredPosts = blogPosts?.filter(post => {
|
const matchesSearch =
|
||||||
const matchesCategory = activeCategory === 'All' || post.category === activeCategory;
|
post.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||||
const matchesSearch = post.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
||||||
post.excerpt.toLowerCase().includes(searchQuery.toLowerCase());
|
post.excerpt.toLowerCase().includes(searchQuery.toLowerCase());
|
||||||
return matchesCategory && matchesSearch;
|
return matchesCategory && matchesSearch;
|
||||||
});
|
});
|
||||||
@@ -48,8 +51,6 @@ export default function Blog() {
|
|||||||
return (
|
return (
|
||||||
<PageTransition>
|
<PageTransition>
|
||||||
<div className="min-h-screen bg-background overflow-x-hidden">
|
<div className="min-h-screen bg-background overflow-x-hidden">
|
||||||
<Navbar />
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="pt-32 pb-16 relative overflow-hidden">
|
<section className="pt-32 pb-16 relative overflow-hidden">
|
||||||
<div className="absolute inset-0">
|
<div className="absolute inset-0">
|
||||||
@@ -81,7 +82,8 @@ export default function Blog() {
|
|||||||
Our <span className="text-primary neon-text-glow">Blog</span>
|
Our <span className="text-primary neon-text-glow">Blog</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
||||||
Insights, tutorials, and thought leadership from our team of experts.
|
Insights, tutorials, and thought leadership from our team of
|
||||||
|
experts.
|
||||||
</p>
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
@@ -114,12 +116,13 @@ export default function Blog() {
|
|||||||
{categories.map((category) => (
|
{categories.map((category) => (
|
||||||
<Button
|
<Button
|
||||||
key={category}
|
key={category}
|
||||||
variant={activeCategory === category ? 'default' : 'outline'}
|
variant={activeCategory === category ? "default" : "outline"}
|
||||||
onClick={() => setActiveCategory(category)}
|
onClick={() => setActiveCategory(category)}
|
||||||
className={`rounded-full px-6 transition-all duration-300 ${activeCategory === category
|
className={`rounded-full px-6 transition-all duration-300 ${
|
||||||
? 'neon-glow bg-primary text-primary-foreground'
|
activeCategory === category
|
||||||
: 'glass border-primary/30 hover:border-primary'
|
? "neon-glow bg-primary text-primary-foreground"
|
||||||
}`}
|
: "glass border-primary/30 hover:border-primary"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{category}
|
{category}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -171,7 +174,10 @@ export default function Blog() {
|
|||||||
</span>
|
</span>
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<Calendar className="w-3 h-3" />
|
<Calendar className="w-3 h-3" />
|
||||||
{new Date(post.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
|
{new Date(post.date).toLocaleDateString("en-US", {
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
})}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<Clock className="w-3 h-3" />
|
<Clock className="w-3 h-3" />
|
||||||
@@ -197,8 +203,6 @@ export default function Blog() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
);
|
);
|
||||||
|
|||||||
+109
-45
@@ -1,21 +1,27 @@
|
|||||||
import { useParams, Link, useNavigate } from 'react-router-dom';
|
import PageTransition from "@/components/PageTransition";
|
||||||
import { motion } from 'framer-motion';
|
import { Button } from "@/components/ui/button";
|
||||||
import { ArrowLeft, Calendar, Clock, Twitter, Linkedin, Facebook, Link2 } from 'lucide-react';
|
import { getRelatedPosts } from "@/data/blogData";
|
||||||
import { Button } from '@/components/ui/button';
|
import { useBlogById } from "@/hooks/queires/useBlogs";
|
||||||
import { toast } from 'sonner';
|
import { motion } from "framer-motion";
|
||||||
import ReactMarkdown from 'react-markdown';
|
import {
|
||||||
import remarkGfm from 'remark-gfm';
|
ArrowLeft,
|
||||||
import Navbar from '@/components/Navbar';
|
Calendar,
|
||||||
import Footer from '@/components/Footer';
|
Clock,
|
||||||
import PageTransition from '@/components/PageTransition';
|
Facebook,
|
||||||
import { getPostBySlug, getRelatedPosts } from '@/data/blogData';
|
Link2,
|
||||||
import { useBlogById } from '@/hooks/queires/useBlogs';
|
Linkedin,
|
||||||
|
Twitter,
|
||||||
|
} from "lucide-react";
|
||||||
|
import ReactMarkdown from "react-markdown";
|
||||||
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||||
|
import remarkGfm from "remark-gfm";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export default function BlogArticle() {
|
export default function BlogArticle() {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const {data} = useBlogById(id);
|
const { data } = useBlogById(id);
|
||||||
|
|
||||||
const post = data?.data.data
|
const post = data?.data.data;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
// const post = getPostBySlug(id || '');
|
// const post = getPostBySlug(id || '');
|
||||||
|
|
||||||
@@ -25,8 +31,10 @@ export default function BlogArticle() {
|
|||||||
<div className="min-h-screen bg-background flex items-center justify-center">
|
<div className="min-h-screen bg-background flex items-center justify-center">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h1 className="text-4xl font-bold mb-4">Article Not Found</h1>
|
<h1 className="text-4xl font-bold mb-4">Article Not Found</h1>
|
||||||
<p className="text-muted-foreground mb-8">The article you're looking for doesn't exist.</p>
|
<p className="text-muted-foreground mb-8">
|
||||||
<Button onClick={() => navigate('/blog')}>Back to Blog</Button>
|
The article you're looking for doesn't exist.
|
||||||
|
</p>
|
||||||
|
<Button onClick={() => navigate("/blog")}>Back to Blog</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
@@ -43,19 +51,17 @@ export default function BlogArticle() {
|
|||||||
facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(shareUrl)}`,
|
facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(shareUrl)}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (platform === 'copy') {
|
if (platform === "copy") {
|
||||||
navigator.clipboard.writeText(shareUrl);
|
navigator.clipboard.writeText(shareUrl);
|
||||||
toast.success('Link copied to clipboard!');
|
toast.success("Link copied to clipboard!");
|
||||||
} else {
|
} else {
|
||||||
window.open(urls[platform], '_blank', 'width=600,height=400');
|
window.open(urls[platform], "_blank", "width=600,height=400");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageTransition>
|
<PageTransition>
|
||||||
<div className="min-h-screen bg-background overflow-x-hidden">
|
<div className="min-h-screen bg-background overflow-x-hidden">
|
||||||
<Navbar />
|
|
||||||
|
|
||||||
{/* Hero */}
|
{/* Hero */}
|
||||||
<section className="pt-32 pb-16 relative overflow-hidden">
|
<section className="pt-32 pb-16 relative overflow-hidden">
|
||||||
<div className="absolute inset-0">
|
<div className="absolute inset-0">
|
||||||
@@ -110,13 +116,19 @@ export default function BlogArticle() {
|
|||||||
className="w-10 h-10 rounded-full object-cover border-2 border-primary/50"
|
className="w-10 h-10 rounded-full object-cover border-2 border-primary/50"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium text-foreground">{post.author.name}</p>
|
<p className="font-medium text-foreground">
|
||||||
|
{post.author.name}
|
||||||
|
</p>
|
||||||
<p className="text-sm">{post.author.role}</p>
|
<p className="text-sm">{post.author.role}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span className="flex items-center gap-2">
|
<span className="flex items-center gap-2">
|
||||||
<Calendar className="w-4 h-4" />
|
<Calendar className="w-4 h-4" />
|
||||||
{new Date(post.date).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })}
|
{new Date(post.date).toLocaleDateString("en-US", {
|
||||||
|
month: "long",
|
||||||
|
day: "numeric",
|
||||||
|
year: "numeric",
|
||||||
|
})}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex items-center gap-2">
|
<span className="flex items-center gap-2">
|
||||||
<Clock className="w-4 h-4" />
|
<Clock className="w-4 h-4" />
|
||||||
@@ -154,17 +166,57 @@ export default function BlogArticle() {
|
|||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
remarkPlugins={[remarkGfm]}
|
remarkPlugins={[remarkGfm]}
|
||||||
components={{
|
components={{
|
||||||
h1: ({ children }) => <h1 className="text-3xl font-bold text-foreground mt-8 mb-4">{children}</h1>,
|
h1: ({ children }) => (
|
||||||
h2: ({ children }) => <h2 className="text-2xl font-bold text-foreground mt-8 mb-4">{children}</h2>,
|
<h1 className="text-3xl font-bold text-foreground mt-8 mb-4">
|
||||||
h3: ({ children }) => <h3 className="text-xl font-bold text-foreground mt-6 mb-3">{children}</h3>,
|
{children}
|
||||||
h4: ({ children }) => <h4 className="text-lg font-bold text-foreground mt-4 mb-2">{children}</h4>,
|
</h1>
|
||||||
p: ({ children }) => <p className="text-muted-foreground leading-relaxed mb-4">{children}</p>,
|
),
|
||||||
ul: ({ children }) => <ul className="list-disc list-inside text-muted-foreground space-y-2 mb-4 ml-4">{children}</ul>,
|
h2: ({ children }) => (
|
||||||
ol: ({ children }) => <ol className="list-decimal list-inside text-muted-foreground space-y-2 mb-4 ml-4">{children}</ol>,
|
<h2 className="text-2xl font-bold text-foreground mt-8 mb-4">
|
||||||
li: ({ children }) => <li className="text-muted-foreground">{children}</li>,
|
{children}
|
||||||
a: ({ href, children }) => <a href={href} className="text-primary hover:underline">{children}</a>,
|
</h2>
|
||||||
strong: ({ children }) => <strong className="font-bold text-foreground">{children}</strong>,
|
),
|
||||||
em: ({ children }) => <em className="italic">{children}</em>,
|
h3: ({ children }) => (
|
||||||
|
<h3 className="text-xl font-bold text-foreground mt-6 mb-3">
|
||||||
|
{children}
|
||||||
|
</h3>
|
||||||
|
),
|
||||||
|
h4: ({ children }) => (
|
||||||
|
<h4 className="text-lg font-bold text-foreground mt-4 mb-2">
|
||||||
|
{children}
|
||||||
|
</h4>
|
||||||
|
),
|
||||||
|
p: ({ children }) => (
|
||||||
|
<p className="text-muted-foreground leading-relaxed mb-4">
|
||||||
|
{children}
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
ul: ({ children }) => (
|
||||||
|
<ul className="list-disc list-inside text-muted-foreground space-y-2 mb-4 ml-4">
|
||||||
|
{children}
|
||||||
|
</ul>
|
||||||
|
),
|
||||||
|
ol: ({ children }) => (
|
||||||
|
<ol className="list-decimal list-inside text-muted-foreground space-y-2 mb-4 ml-4">
|
||||||
|
{children}
|
||||||
|
</ol>
|
||||||
|
),
|
||||||
|
li: ({ children }) => (
|
||||||
|
<li className="text-muted-foreground">{children}</li>
|
||||||
|
),
|
||||||
|
a: ({ href, children }) => (
|
||||||
|
<a href={href} className="text-primary hover:underline">
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
),
|
||||||
|
strong: ({ children }) => (
|
||||||
|
<strong className="font-bold text-foreground">
|
||||||
|
{children}
|
||||||
|
</strong>
|
||||||
|
),
|
||||||
|
em: ({ children }) => (
|
||||||
|
<em className="italic">{children}</em>
|
||||||
|
),
|
||||||
blockquote: ({ children }) => (
|
blockquote: ({ children }) => (
|
||||||
<blockquote className="border-l-4 border-primary pl-4 italic text-muted-foreground my-4">
|
<blockquote className="border-l-4 border-primary pl-4 italic text-muted-foreground my-4">
|
||||||
{children}
|
{children}
|
||||||
@@ -173,7 +225,11 @@ export default function BlogArticle() {
|
|||||||
code: ({ className, children }) => {
|
code: ({ className, children }) => {
|
||||||
const isInline = !className;
|
const isInline = !className;
|
||||||
if (isInline) {
|
if (isInline) {
|
||||||
return <code className="bg-muted px-1.5 py-0.5 rounded text-sm font-mono">{children}</code>;
|
return (
|
||||||
|
<code className="bg-muted px-1.5 py-0.5 rounded text-sm font-mono">
|
||||||
|
{children}
|
||||||
|
</code>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<code className="block bg-muted border border-border rounded-lg p-4 overflow-x-auto text-sm font-mono my-4">
|
<code className="block bg-muted border border-border rounded-lg p-4 overflow-x-auto text-sm font-mono my-4">
|
||||||
@@ -181,7 +237,11 @@ export default function BlogArticle() {
|
|||||||
</code>
|
</code>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
pre: ({ children }) => <pre className="bg-muted border border-border rounded-lg p-4 overflow-x-auto my-4">{children}</pre>,
|
pre: ({ children }) => (
|
||||||
|
<pre className="bg-muted border border-border rounded-lg p-4 overflow-x-auto my-4">
|
||||||
|
{children}
|
||||||
|
</pre>
|
||||||
|
),
|
||||||
hr: () => <hr className="border-border my-8" />,
|
hr: () => <hr className="border-border my-8" />,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -194,12 +254,14 @@ export default function BlogArticle() {
|
|||||||
<div className="sticky top-32 space-y-8">
|
<div className="sticky top-32 space-y-8">
|
||||||
{/* Share */}
|
{/* Share */}
|
||||||
<div className="glass rounded-2xl p-6">
|
<div className="glass rounded-2xl p-6">
|
||||||
<h4 className="font-bold mb-4 text-sm uppercase tracking-wide text-muted-foreground">Share</h4>
|
<h4 className="font-bold mb-4 text-sm uppercase tracking-wide text-muted-foreground">
|
||||||
|
Share
|
||||||
|
</h4>
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => handleShare('twitter')}
|
onClick={() => handleShare("twitter")}
|
||||||
className="justify-start gap-2 glass border-primary/30"
|
className="justify-start gap-2 glass border-primary/30"
|
||||||
>
|
>
|
||||||
<Twitter className="w-4 h-4" /> Twitter
|
<Twitter className="w-4 h-4" /> Twitter
|
||||||
@@ -207,7 +269,7 @@ export default function BlogArticle() {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => handleShare('linkedin')}
|
onClick={() => handleShare("linkedin")}
|
||||||
className="justify-start gap-2 glass border-primary/30"
|
className="justify-start gap-2 glass border-primary/30"
|
||||||
>
|
>
|
||||||
<Linkedin className="w-4 h-4" /> LinkedIn
|
<Linkedin className="w-4 h-4" /> LinkedIn
|
||||||
@@ -215,7 +277,7 @@ export default function BlogArticle() {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => handleShare('facebook')}
|
onClick={() => handleShare("facebook")}
|
||||||
className="justify-start gap-2 glass border-primary/30"
|
className="justify-start gap-2 glass border-primary/30"
|
||||||
>
|
>
|
||||||
<Facebook className="w-4 h-4" /> Facebook
|
<Facebook className="w-4 h-4" /> Facebook
|
||||||
@@ -223,7 +285,7 @@ export default function BlogArticle() {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => handleShare('copy')}
|
onClick={() => handleShare("copy")}
|
||||||
className="justify-start gap-2 glass border-primary/30"
|
className="justify-start gap-2 glass border-primary/30"
|
||||||
>
|
>
|
||||||
<Link2 className="w-4 h-4" /> Copy Link
|
<Link2 className="w-4 h-4" /> Copy Link
|
||||||
@@ -233,7 +295,9 @@ export default function BlogArticle() {
|
|||||||
|
|
||||||
{/* Tags */}
|
{/* Tags */}
|
||||||
<div className="glass rounded-2xl p-6">
|
<div className="glass rounded-2xl p-6">
|
||||||
<h4 className="font-bold mb-4 text-sm uppercase tracking-wide text-muted-foreground">Tags</h4>
|
<h4 className="font-bold mb-4 text-sm uppercase tracking-wide text-muted-foreground">
|
||||||
|
Tags
|
||||||
|
</h4>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{post.tags.map((tag) => (
|
{post.tags.map((tag) => (
|
||||||
<span
|
<span
|
||||||
@@ -267,7 +331,9 @@ export default function BlogArticle() {
|
|||||||
/>
|
/>
|
||||||
<div className="text-center md:text-left">
|
<div className="text-center md:text-left">
|
||||||
<h3 className="text-2xl font-bold mb-2">{post.author.name}</h3>
|
<h3 className="text-2xl font-bold mb-2">{post.author.name}</h3>
|
||||||
<p className="text-primary font-medium mb-4">{post.author.role}</p>
|
<p className="text-primary font-medium mb-4">
|
||||||
|
{post.author.role}
|
||||||
|
</p>
|
||||||
<p className="text-muted-foreground mb-4">{post.author.bio}</p>
|
<p className="text-muted-foreground mb-4">{post.author.bio}</p>
|
||||||
<div className="flex gap-3 justify-center md:justify-start">
|
<div className="flex gap-3 justify-center md:justify-start">
|
||||||
{post.author.twitter && (
|
{post.author.twitter && (
|
||||||
@@ -342,8 +408,6 @@ export default function BlogArticle() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,18 +1,23 @@
|
|||||||
import { useParams, Link, useNavigate } from 'react-router-dom';
|
import PageTransition from "@/components/PageTransition";
|
||||||
import { motion } from 'framer-motion';
|
import { Button } from "@/components/ui/button";
|
||||||
import { ArrowLeft, ExternalLink, Github, Calendar, Clock, Users, ChevronRight } from 'lucide-react';
|
import { getProjectBySlug, getRelatedProjects } from "@/data/projectData";
|
||||||
import { Button } from '@/components/ui/button';
|
import { motion } from "framer-motion";
|
||||||
import ReactMarkdown from 'react-markdown';
|
import {
|
||||||
import remarkGfm from 'remark-gfm';
|
Calendar,
|
||||||
import Navbar from '@/components/Navbar';
|
ChevronRight,
|
||||||
import Footer from '@/components/Footer';
|
Clock,
|
||||||
import PageTransition from '@/components/PageTransition';
|
ExternalLink,
|
||||||
import { getProjectBySlug, getRelatedProjects } from '@/data/projectData';
|
Github,
|
||||||
|
Users,
|
||||||
|
} from "lucide-react";
|
||||||
|
import ReactMarkdown from "react-markdown";
|
||||||
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||||
|
import remarkGfm from "remark-gfm";
|
||||||
|
|
||||||
export default function ProjectDetails() {
|
export default function ProjectDetails() {
|
||||||
const { slug } = useParams<{ slug: string }>();
|
const { slug } = useParams<{ slug: string }>();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const project = getProjectBySlug(slug || '');
|
const project = getProjectBySlug(slug || "");
|
||||||
|
|
||||||
if (!project) {
|
if (!project) {
|
||||||
return (
|
return (
|
||||||
@@ -20,8 +25,12 @@ export default function ProjectDetails() {
|
|||||||
<div className="min-h-screen bg-background flex items-center justify-center">
|
<div className="min-h-screen bg-background flex items-center justify-center">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h1 className="text-4xl font-bold mb-4">Project Not Found</h1>
|
<h1 className="text-4xl font-bold mb-4">Project Not Found</h1>
|
||||||
<p className="text-muted-foreground mb-8">The project you're looking for doesn't exist.</p>
|
<p className="text-muted-foreground mb-8">
|
||||||
<Button onClick={() => navigate('/projects')}>Back to Projects</Button>
|
The project you're looking for doesn't exist.
|
||||||
|
</p>
|
||||||
|
<Button onClick={() => navigate("/projects")}>
|
||||||
|
Back to Projects
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
@@ -30,17 +39,15 @@ export default function ProjectDetails() {
|
|||||||
|
|
||||||
const relatedProjects = getRelatedProjects(project);
|
const relatedProjects = getRelatedProjects(project);
|
||||||
const categoryLabels: Record<string, string> = {
|
const categoryLabels: Record<string, string> = {
|
||||||
web: 'Web Development',
|
web: "Web Development",
|
||||||
mobile: 'Mobile App',
|
mobile: "Mobile App",
|
||||||
ai: 'AI & Machine Learning',
|
ai: "AI & Machine Learning",
|
||||||
cloud: 'Cloud Solutions',
|
cloud: "Cloud Solutions",
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageTransition>
|
<PageTransition>
|
||||||
<div className="min-h-screen bg-background overflow-x-hidden">
|
<div className="min-h-screen bg-background overflow-x-hidden">
|
||||||
<Navbar />
|
|
||||||
|
|
||||||
{/* Hero */}
|
{/* Hero */}
|
||||||
<section className="pt-32 pb-16 relative overflow-hidden">
|
<section className="pt-32 pb-16 relative overflow-hidden">
|
||||||
<div className="absolute inset-0">
|
<div className="absolute inset-0">
|
||||||
@@ -56,9 +63,16 @@ export default function ProjectDetails() {
|
|||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
className="flex items-center gap-2 text-sm text-muted-foreground mb-8"
|
className="flex items-center gap-2 text-sm text-muted-foreground mb-8"
|
||||||
>
|
>
|
||||||
<Link to="/" className="hover:text-primary transition-colors">Home</Link>
|
<Link to="/" className="hover:text-primary transition-colors">
|
||||||
|
Home
|
||||||
|
</Link>
|
||||||
<ChevronRight className="w-4 h-4" />
|
<ChevronRight className="w-4 h-4" />
|
||||||
<Link to="/projects" className="hover:text-primary transition-colors">Projects</Link>
|
<Link
|
||||||
|
to="/projects"
|
||||||
|
className="hover:text-primary transition-colors"
|
||||||
|
>
|
||||||
|
Projects
|
||||||
|
</Link>
|
||||||
<ChevronRight className="w-4 h-4" />
|
<ChevronRight className="w-4 h-4" />
|
||||||
<span className="text-foreground">{project.title}</span>
|
<span className="text-foreground">{project.title}</span>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -132,7 +146,10 @@ export default function ProjectDetails() {
|
|||||||
<ExternalLink className="w-4 h-4 mr-2" />
|
<ExternalLink className="w-4 h-4 mr-2" />
|
||||||
View Live
|
View Live
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="outline" className="rounded-full glass border-primary/30">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="rounded-full glass border-primary/30"
|
||||||
|
>
|
||||||
<Github className="w-4 h-4 mr-2" />
|
<Github className="w-4 h-4 mr-2" />
|
||||||
View Code
|
View Code
|
||||||
</Button>
|
</Button>
|
||||||
@@ -181,7 +198,9 @@ export default function ProjectDetails() {
|
|||||||
<p className="text-3xl md:text-4xl font-bold text-primary neon-text-glow mb-2">
|
<p className="text-3xl md:text-4xl font-bold text-primary neon-text-glow mb-2">
|
||||||
{result.value}
|
{result.value}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-muted-foreground text-sm">{result.label}</p>
|
<p className="text-muted-foreground text-sm">
|
||||||
|
{result.label}
|
||||||
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -203,10 +222,24 @@ export default function ProjectDetails() {
|
|||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
remarkPlugins={[remarkGfm]}
|
remarkPlugins={[remarkGfm]}
|
||||||
components={{
|
components={{
|
||||||
p: ({ children }) => <p className="text-muted-foreground leading-relaxed mb-4">{children}</p>,
|
p: ({ children }) => (
|
||||||
strong: ({ children }) => <strong className="font-bold text-foreground">{children}</strong>,
|
<p className="text-muted-foreground leading-relaxed mb-4">
|
||||||
ul: ({ children }) => <ul className="list-disc list-inside text-muted-foreground space-y-2 mb-4 ml-4">{children}</ul>,
|
{children}
|
||||||
li: ({ children }) => <li className="text-muted-foreground">{children}</li>,
|
</p>
|
||||||
|
),
|
||||||
|
strong: ({ children }) => (
|
||||||
|
<strong className="font-bold text-foreground">
|
||||||
|
{children}
|
||||||
|
</strong>
|
||||||
|
),
|
||||||
|
ul: ({ children }) => (
|
||||||
|
<ul className="list-disc list-inside text-muted-foreground space-y-2 mb-4 ml-4">
|
||||||
|
{children}
|
||||||
|
</ul>
|
||||||
|
),
|
||||||
|
li: ({ children }) => (
|
||||||
|
<li className="text-muted-foreground">{children}</li>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{project.fullDescription}
|
{project.fullDescription}
|
||||||
@@ -262,7 +295,9 @@ export default function ProjectDetails() {
|
|||||||
{project.challenges.map((challenge, index) => (
|
{project.challenges.map((challenge, index) => (
|
||||||
<li key={index} className="flex items-start gap-3">
|
<li key={index} className="flex items-start gap-3">
|
||||||
<span className="w-2 h-2 rounded-full bg-neon-purple mt-2 flex-shrink-0" />
|
<span className="w-2 h-2 rounded-full bg-neon-purple mt-2 flex-shrink-0" />
|
||||||
<span className="text-muted-foreground">{challenge}</span>
|
<span className="text-muted-foreground">
|
||||||
|
{challenge}
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -356,7 +391,10 @@ export default function ProjectDetails() {
|
|||||||
className="text-center mt-12"
|
className="text-center mt-12"
|
||||||
>
|
>
|
||||||
<Link to="/projects">
|
<Link to="/projects">
|
||||||
<Button variant="outline" className="rounded-full px-8 glass border-primary/30 hover:neon-glow">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="rounded-full px-8 glass border-primary/30 hover:neon-glow"
|
||||||
|
>
|
||||||
View All Projects
|
View All Projects
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -364,8 +402,6 @@ export default function ProjectDetails() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
);
|
);
|
||||||
|
|||||||
+45
-35
@@ -1,21 +1,27 @@
|
|||||||
import { useState } from 'react';
|
import PageTransition from "@/components/PageTransition";
|
||||||
import { motion, AnimatePresence, calcLength } from 'framer-motion';
|
import { Button } from "@/components/ui/button";
|
||||||
import { ArrowLeft, Globe, Smartphone, Brain, Cloud, ExternalLink, Workflow, Github } from 'lucide-react';
|
import { useProjects } from "@/hooks/queires/useProjects";
|
||||||
import { Link } from 'react-router-dom';
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
import { Button } from '@/components/ui/button';
|
import {
|
||||||
import Navbar from '@/components/Navbar';
|
ArrowLeft,
|
||||||
import Footer from '@/components/Footer';
|
Brain,
|
||||||
import PageTransition from '@/components/PageTransition';
|
Cloud,
|
||||||
import { useProjects } from '@/hooks/queires/useProjects';
|
ExternalLink,
|
||||||
import { projects } from '@/data/projectData';
|
Github,
|
||||||
|
Globe,
|
||||||
|
Smartphone,
|
||||||
|
Workflow,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
const categories = [
|
const categories = [
|
||||||
{ id: 'all', name: 'All Projects', icon: null },
|
{ id: "all", name: "All Projects", icon: null },
|
||||||
{ id: 'web', name: 'Web', icon: Globe },
|
{ id: "web", name: "Web", icon: Globe },
|
||||||
{ id: 'mobile', name: 'Mobile', icon: Smartphone },
|
{ id: "mobile", name: "Mobile", icon: Smartphone },
|
||||||
{ id: 'ai', name: 'AI', icon: Brain },
|
{ id: "ai", name: "AI", icon: Brain },
|
||||||
{ id: 'cloud', name: 'Cloud', icon: Cloud },
|
{ id: "cloud", name: "Cloud", icon: Cloud },
|
||||||
{ id: 'devops', name: 'DEVOPS', icon: Workflow },
|
{ id: "devops", name: "DEVOPS", icon: Workflow },
|
||||||
];
|
];
|
||||||
|
|
||||||
const containerVariants = {
|
const containerVariants = {
|
||||||
@@ -33,26 +39,24 @@ const itemVariants = {
|
|||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
transition: { duration: 0.5, ease: 'easeOut' as const },
|
transition: { duration: 0.5, ease: "easeOut" as const },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Projects() {
|
export default function Projects() {
|
||||||
|
const { data: projectsData } = useProjects();
|
||||||
const {data: projectsData} = useProjects();
|
|
||||||
const projects = projectsData?.data.data.result;
|
const projects = projectsData?.data.data.result;
|
||||||
|
|
||||||
const [activeCategory, setActiveCategory] = useState('all');
|
const [activeCategory, setActiveCategory] = useState("all");
|
||||||
|
|
||||||
const filteredProjects = activeCategory === 'all'
|
const filteredProjects =
|
||||||
? projects
|
activeCategory === "all"
|
||||||
: projects?.filter(project => project.category === activeCategory);
|
? projects
|
||||||
|
: projects?.filter((project) => project.category === activeCategory);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageTransition>
|
<PageTransition>
|
||||||
<div className="min-h-screen bg-background overflow-x-hidden">
|
<div className="min-h-screen bg-background overflow-x-hidden">
|
||||||
<Navbar />
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="pt-32 pb-16 relative overflow-hidden">
|
<section className="pt-32 pb-16 relative overflow-hidden">
|
||||||
<div className="absolute inset-0">
|
<div className="absolute inset-0">
|
||||||
@@ -83,10 +87,12 @@ export default function Projects() {
|
|||||||
className="text-center mb-12"
|
className="text-center mb-12"
|
||||||
>
|
>
|
||||||
<h1 className="text-5xl md:text-6xl font-bold mb-6">
|
<h1 className="text-5xl md:text-6xl font-bold mb-6">
|
||||||
Our <span className="text-primary neon-text-glow">Projects</span>
|
Our{" "}
|
||||||
|
<span className="text-primary neon-text-glow">Projects</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
||||||
Explore our portfolio of innovative solutions that have transformed businesses across industries.
|
Explore our portfolio of innovative solutions that have
|
||||||
|
transformed businesses across industries.
|
||||||
</p>
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
@@ -102,12 +108,15 @@ export default function Projects() {
|
|||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
key={category.id}
|
key={category.id}
|
||||||
variant={activeCategory === category.id ? 'default' : 'outline'}
|
variant={
|
||||||
|
activeCategory === category.id ? "default" : "outline"
|
||||||
|
}
|
||||||
onClick={() => setActiveCategory(category.id)}
|
onClick={() => setActiveCategory(category.id)}
|
||||||
className={`rounded-full px-6 transition-all duration-300 ${activeCategory === category.id
|
className={`rounded-full px-6 transition-all duration-300 ${
|
||||||
? 'neon-glow bg-primary text-primary-foreground'
|
activeCategory === category.id
|
||||||
: 'glass border-primary/30 hover:border-primary'
|
? "neon-glow bg-primary text-primary-foreground"
|
||||||
}`}
|
: "glass border-primary/30 hover:border-primary"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{Icon && <Icon className="w-4 h-4 mr-2" />}
|
{Icon && <Icon className="w-4 h-4 mr-2" />}
|
||||||
{category.name}
|
{category.name}
|
||||||
@@ -149,7 +158,10 @@ export default function Projects() {
|
|||||||
{/* Category Badge */}
|
{/* Category Badge */}
|
||||||
<div className="absolute top-4 left-4">
|
<div className="absolute top-4 left-4">
|
||||||
<span className="px-3 py-1 rounded-full bg-primary/20 text-primary text-sm font-medium backdrop-blur-sm border border-primary/30">
|
<span className="px-3 py-1 rounded-full bg-primary/20 text-primary text-sm font-medium backdrop-blur-sm border border-primary/30">
|
||||||
{categories.find(c => c.id === project.category)?.name}
|
{
|
||||||
|
categories.find((c) => c.id === project.category)
|
||||||
|
?.name
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -222,8 +234,6 @@ export default function Projects() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
</PageTransition>
|
</PageTransition>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user