implement tanstack and fetch all data
This commit is contained in:
+4
-4
@@ -11,12 +11,12 @@ import ProjectDetails from "./pages/ProjectDetails";
|
||||
import Blog from "./pages/Blog";
|
||||
import BlogArticle from "./pages/BlogArticle";
|
||||
import NotFound from "./pages/NotFound";
|
||||
import { QueryProvider } from "./provider/QueryProvider";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
function AnimatedRoutes() {
|
||||
const location = useLocation();
|
||||
|
||||
|
||||
return (
|
||||
<AnimatePresence mode="wait">
|
||||
<Routes location={location} key={location.pathname}>
|
||||
@@ -33,7 +33,7 @@ function AnimatedRoutes() {
|
||||
}
|
||||
|
||||
const App = () => (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<QueryProvider>
|
||||
<ThemeProvider>
|
||||
<TooltipProvider>
|
||||
<Toaster />
|
||||
@@ -43,7 +43,7 @@ const App = () => (
|
||||
</BrowserRouter>
|
||||
</TooltipProvider>
|
||||
</ThemeProvider>
|
||||
</QueryClientProvider>
|
||||
</QueryProvider>
|
||||
);
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import axios from "axios";
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_URL,
|
||||
timeout: 5000,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
export default axiosInstance;
|
||||
@@ -0,0 +1,24 @@
|
||||
import { T_blogs } from "@/types/blogs.type";
|
||||
import axiosInstance from "../axiosInstance";
|
||||
|
||||
export interface IBlogQueryParams {
|
||||
[key: string]: string | number | boolean | undefined;
|
||||
}
|
||||
|
||||
|
||||
export const blogService = {
|
||||
getBlogs: (params?: IBlogQueryParams) =>
|
||||
axiosInstance.get("/api/blogs", { params }).then(res => res.data),
|
||||
|
||||
getBlogById: (id: string) =>
|
||||
axiosInstance.get(`/api/blogs/${id}`),
|
||||
|
||||
createBlog: (data: Partial<T_blogs>) =>
|
||||
axiosInstance.post("/api/blogs", data),
|
||||
|
||||
updateBlog: (id: string, data: Partial<T_blogs>) =>
|
||||
axiosInstance.patch(`/api/blogs/${id}`, data),
|
||||
|
||||
deleteBlog: (id: string) =>
|
||||
axiosInstance.delete(`/api/blogs/${id}`),
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import { T_projects } from '@/types/projects.type';
|
||||
import axiosInstance from './../axiosInstance';
|
||||
|
||||
export interface IProjectsQueryParams {
|
||||
[key: string]: string | number | boolean | undefined;
|
||||
}
|
||||
|
||||
|
||||
export const projectsService = {
|
||||
getProjects: (params?: IProjectsQueryParams) =>
|
||||
axiosInstance.get("/api/projects", { params }),
|
||||
|
||||
getProjectById: (id: string) =>
|
||||
axiosInstance.get(`/api/projects/${id}`),
|
||||
|
||||
createProject: (data: Partial<T_projects>) =>
|
||||
axiosInstance.post("/api/projects", data),
|
||||
|
||||
updateProject: (id: string, data: Partial<T_projects>) =>
|
||||
axiosInstance.patch(`/api/projects/${id}`, data),
|
||||
|
||||
deleteProject: (id: string) =>
|
||||
axiosInstance.delete(`/api/projects/${id}`),
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import { T_reviews } from '@/types/review.type';
|
||||
import axiosInstance from './../axiosInstance';
|
||||
|
||||
|
||||
export const reviewsService = {
|
||||
getReviews: () =>
|
||||
axiosInstance.get("/api/reviews"),
|
||||
|
||||
getReviewById: (id: string) =>
|
||||
axiosInstance.get(`/api/reviews/${id}`),
|
||||
|
||||
createReview: (data: Partial<T_reviews>) =>
|
||||
axiosInstance.post("/api/reviews", data),
|
||||
|
||||
updateReview: (id: string, data: Partial<T_reviews>) =>
|
||||
axiosInstance.patch(`/api/reviews/${id}`, data),
|
||||
|
||||
deleteReview: (id: string) =>
|
||||
axiosInstance.delete(`/api/reviews/${id}`),
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import { T_team } from '@/types/team.type';
|
||||
import axiosInstance from './../axiosInstance';
|
||||
|
||||
export const teamService = {
|
||||
getTeams: () =>
|
||||
axiosInstance.get("/api/team"),
|
||||
|
||||
getTeamById: (id: string) =>
|
||||
axiosInstance.get(`/api/team/${id}`),
|
||||
|
||||
createTeam: (data: Partial<T_team>) =>
|
||||
axiosInstance.post("/api/team", data),
|
||||
|
||||
updateTeam: (id: string, data: Partial<T_team>) =>
|
||||
axiosInstance.patch(`/api/team/${id}`, data),
|
||||
|
||||
deleteTeam: (id: string) =>
|
||||
axiosInstance.delete(`/api/team/${id}`),
|
||||
};
|
||||
@@ -8,72 +8,19 @@ import { Swiper, SwiperSlide } from "swiper/react";
|
||||
// Import Swiper styles
|
||||
import "swiper/css";
|
||||
import "swiper/css/pagination";
|
||||
import { useTeam } from "@/hooks/queires/useTeam";
|
||||
|
||||
const team = [
|
||||
// {
|
||||
// name: "Md Abumahid Islam",
|
||||
// role: "CEO & Founder",
|
||||
// image:
|
||||
// "https://res.cloudinary.com/dnxsk9rgl/image/upload/v1772734622/abumahid_ghax5c.png",
|
||||
// bio: "Visionary founder building innovative digital technology solutions.",
|
||||
// github: "https://github.com/abumahid",
|
||||
// twitter: "https://x.com/Abumahidislam",
|
||||
// linkedin: "https://www.linkedin.com/in/md-abu-mahid-islam",
|
||||
// },
|
||||
{
|
||||
name: "Rimi Rahman",
|
||||
role: "Front-end Developer",
|
||||
image:
|
||||
"https://res.cloudinary.com/dnxsk9rgl/image/upload/v1772735809/rimi_easbn4.png",
|
||||
bio: "Technology leader designing scalable and reliable software systems.",
|
||||
github: "https://github.com/sanjidaRimi023",
|
||||
twitter: "",
|
||||
linkedin: "https://www.linkedin.com/in/sanjidarimi023/",
|
||||
},
|
||||
{
|
||||
name: "Utsob Saha",
|
||||
role: "Social Media Manager",
|
||||
image:
|
||||
"https://res.cloudinary.com/dnxsk9rgl/image/upload/v1772733893/utsob_txy0qe.png",
|
||||
bio: "Driving brand growth through creative social media strategy.",
|
||||
github: "https://github.com/Utsob1621",
|
||||
twitter: "",
|
||||
linkedin: "https://www.linkedin.com/in/utsob-saha-211894350/",
|
||||
},
|
||||
{
|
||||
name: "Yeassin Ali",
|
||||
role: "Front-end Developer",
|
||||
image:
|
||||
"https://res.cloudinary.com/dnxsk9rgl/image/upload/v1772735363/yeassing_pf6ta6.png",
|
||||
bio: "Frontend specialist creating fast and responsive web interfaces.",
|
||||
github: "https://github.com/Yeassin7376",
|
||||
twitter: "",
|
||||
linkedin: "https://www.linkedin.com/in/yeassin-ali17/",
|
||||
},
|
||||
|
||||
{
|
||||
name: "Sharafat Hossain",
|
||||
role: "Front-end Developer",
|
||||
image:
|
||||
"https://res.cloudinary.com/dnxsk9rgl/image/upload/v1772736523/sharafat_pydaih.png",
|
||||
bio: "Building modern web applications with full stack expertise.",
|
||||
github: "https://github.com/dev-sharafat",
|
||||
twitter: "",
|
||||
linkedin: "https://www.linkedin.com/in/sharafathassain23/",
|
||||
},
|
||||
{
|
||||
name: "Ripa Akter Badhon",
|
||||
role: "HR Manager",
|
||||
image:
|
||||
"https://res.cloudinary.com/dnxsk9rgl/image/upload/v1772991488/badhon_ny4nsr.png",
|
||||
bio: "Supporting team growth and employee wellbeing.",
|
||||
github: "",
|
||||
twitter: "",
|
||||
linkedin: "",
|
||||
},
|
||||
];
|
||||
|
||||
export default function TeamSection() {
|
||||
|
||||
const {data: teamdata} = useTeam();
|
||||
|
||||
const team = teamdata?.data.data;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const ref = useRef<HTMLElement>(null);
|
||||
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
||||
const shouldScroll = team.length >= 5;
|
||||
|
||||
@@ -540,6 +540,8 @@ LLMs are powerful tools, but they require thoughtful implementation. Start with
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
export const getPostBySlug = (slug: string): BlogPost | undefined => {
|
||||
return blogPosts.find(post => post.slug === slug);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export enum BlogCategory {
|
||||
WEB_DEVELOPMENT = "Web Development",
|
||||
MOBILE_DEVELOPMENT = "Mobile Development",
|
||||
UI_UX_DESIGN = "UI/UX Design",
|
||||
DEVOPS = "DevOps",
|
||||
MACHINE_LEARNING = "Machine Learning",
|
||||
CYBER_SECURITY = "Cyber Security",
|
||||
CLOUD_COMPUTING = "Cloud Computing",
|
||||
DATA_SCIENCE = "Data Science",
|
||||
PROGRAMMING = "Programming",
|
||||
CAREER_GUIDE = "Career Guide",
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum BlogStatus {
|
||||
PUBLISHED = "PUBLISHED",
|
||||
DRAFT = "DRAFT",
|
||||
ARCHIVED = "ARCHIVED"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
export enum ProjectCategory {
|
||||
WEB = "web",
|
||||
MOBILE = "mobile",
|
||||
DESKTOP = "desktop",
|
||||
BACKEND = "backend",
|
||||
FULLSTACK = "fullstack",
|
||||
CLOUD = "cloud",
|
||||
AI = "ai",
|
||||
MACHINE_LEARNING = "machine-learning",
|
||||
DATA_SCIENCE = "data-science",
|
||||
DEVOPS = "devops",
|
||||
ECOMMERCE = "ecommerce",
|
||||
SAAS = "saas",
|
||||
API = "api",
|
||||
BLOCKCHAIN = "blockchain",
|
||||
IOT = "iot"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum ProjectStatus {
|
||||
COMPLETED = "completed",
|
||||
ONGOING = "ongoing",
|
||||
ARCHIVED = "archived"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { blogService, IBlogQueryParams } from "@/api/services/blog.service";
|
||||
import { queryKeys } from "@/utils/queryKeys";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
|
||||
export const useBlogs = (params?: IBlogQueryParams) => {
|
||||
return useQuery({
|
||||
queryKey: [...queryKeys.blogs, params],
|
||||
queryFn: () => blogService.getBlogs(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const useBlogById = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.blog(id),
|
||||
queryFn: () => blogService.getBlogById(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import { IProjectsQueryParams, projectsService } from "@/api/services/project.service";
|
||||
import { queryKeys } from "@/utils/queryKeys";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
|
||||
export const useProjects = (params?: IProjectsQueryParams) => {
|
||||
return useQuery({
|
||||
queryKey: [...queryKeys.projects, params],
|
||||
queryFn: () => projectsService.getProjects(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const useProjectById = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.project(id),
|
||||
queryFn: () => projectsService.getProjectById(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { reviewsService } from "@/api/services/review.service";
|
||||
import { queryKeys } from "@/utils/queryKeys";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
|
||||
export const useReviews = () => {
|
||||
return useQuery({
|
||||
queryKey: [...queryKeys.reviews],
|
||||
queryFn: () => reviewsService.getReviews(),
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { teamService } from "@/api/services/team.service";
|
||||
import { queryKeys } from "@/utils/queryKeys";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
|
||||
export const useTeam = () => {
|
||||
return useQuery({
|
||||
queryKey: [...queryKeys.team],
|
||||
queryFn: () => teamService.getTeams(),
|
||||
});
|
||||
};
|
||||
+11
-6
@@ -8,6 +8,7 @@ import Navbar from '@/components/Navbar';
|
||||
import Footer from '@/components/Footer';
|
||||
import PageTransition from '@/components/PageTransition';
|
||||
import { blogPosts } from '@/data/blogData';
|
||||
import { useBlogs } from './../hooks/queires/useBlogs';
|
||||
|
||||
const categories = ['All', 'AI & Machine Learning', 'Cloud Solutions', 'Web Development', 'Mobile Development'];
|
||||
|
||||
@@ -29,13 +30,18 @@ const itemVariants = {
|
||||
};
|
||||
|
||||
export default function Blog() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const [activeCategory, setActiveCategory] = useState('All');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
const filteredPosts = blogPosts.filter(post => {
|
||||
const matchesCategory = activeCategory === 'All' || post.category === activeCategory;
|
||||
const matchesSearch = post.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
post.excerpt.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
post.excerpt.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
return matchesCategory && matchesSearch;
|
||||
});
|
||||
|
||||
@@ -110,11 +116,10 @@ export default function Blog() {
|
||||
key={category}
|
||||
variant={activeCategory === category ? 'default' : 'outline'}
|
||||
onClick={() => setActiveCategory(category)}
|
||||
className={`rounded-full px-6 transition-all duration-300 ${
|
||||
activeCategory === category
|
||||
? 'neon-glow bg-primary text-primary-foreground'
|
||||
: 'glass border-primary/30 hover:border-primary'
|
||||
}`}
|
||||
className={`rounded-full px-6 transition-all duration-300 ${activeCategory === category
|
||||
? 'neon-glow bg-primary text-primary-foreground'
|
||||
: 'glass border-primary/30 hover:border-primary'
|
||||
}`}
|
||||
>
|
||||
{category}
|
||||
</Button>
|
||||
|
||||
+12
-7
@@ -7,6 +7,10 @@ import Navbar from '@/components/Navbar';
|
||||
import Footer from '@/components/Footer';
|
||||
import PageTransition from '@/components/PageTransition';
|
||||
import { projects } from '@/data/projectData';
|
||||
import { useBlogById, useBlogs } from './../hooks/queires/useBlogs';
|
||||
import { useProjectById, useProjects } from '@/hooks/queires/useProjects';
|
||||
import { useTeam } from '@/hooks/queires/useTeam';
|
||||
import { useReviews } from '@/hooks/queires/useReviews';
|
||||
|
||||
const categories = [
|
||||
{ id: 'all', name: 'All Projects', icon: null },
|
||||
@@ -36,6 +40,8 @@ const itemVariants = {
|
||||
};
|
||||
|
||||
export default function Projects() {
|
||||
|
||||
|
||||
const [activeCategory, setActiveCategory] = useState('all');
|
||||
|
||||
const filteredProjects = activeCategory === 'all'
|
||||
@@ -46,7 +52,7 @@ export default function Projects() {
|
||||
<PageTransition>
|
||||
<div className="min-h-screen bg-background overflow-x-hidden">
|
||||
<Navbar />
|
||||
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="pt-32 pb-16 relative overflow-hidden">
|
||||
<div className="absolute inset-0">
|
||||
@@ -98,11 +104,10 @@ export default function Projects() {
|
||||
key={category.id}
|
||||
variant={activeCategory === category.id ? 'default' : 'outline'}
|
||||
onClick={() => setActiveCategory(category.id)}
|
||||
className={`rounded-full px-6 transition-all duration-300 ${
|
||||
activeCategory === category.id
|
||||
? 'neon-glow bg-primary text-primary-foreground'
|
||||
: 'glass border-primary/30 hover:border-primary'
|
||||
}`}
|
||||
className={`rounded-full px-6 transition-all duration-300 ${activeCategory === category.id
|
||||
? 'neon-glow bg-primary text-primary-foreground'
|
||||
: 'glass border-primary/30 hover:border-primary'
|
||||
}`}
|
||||
>
|
||||
{Icon && <Icon className="w-4 h-4 mr-2" />}
|
||||
{category.name}
|
||||
@@ -140,7 +145,7 @@ export default function Projects() {
|
||||
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-background via-background/50 to-transparent opacity-60" />
|
||||
|
||||
|
||||
{/* Category Badge */}
|
||||
<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">
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 1000 * 60 * 5,
|
||||
refetchOnWindowFocus: false,
|
||||
retry: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const QueryProvider = ({ children }: { children: ReactNode }) => {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
import { BlogCategory } from "@/enums/blogCategory";
|
||||
import { BlogStatus } from "@/enums/blogStatus";
|
||||
|
||||
export type T_socialLinks = {
|
||||
github: string;
|
||||
linkedin?: string;
|
||||
twitter?: string;
|
||||
portfolio?: string;
|
||||
facebook?: string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export type T_blogs = {
|
||||
title: string;
|
||||
content_description: string;
|
||||
thumbnail: string;
|
||||
images?: string[];
|
||||
authorName: string;
|
||||
authorImage: string;
|
||||
authorDesignation: string;
|
||||
authorEmail: string;
|
||||
socialMediaLink: T_socialLinks;
|
||||
category: BlogCategory;
|
||||
tags: string[];
|
||||
isFeatured: boolean;
|
||||
status: BlogStatus;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { ProjectCategory } from "@/enums/projectCategory";
|
||||
import { ProjectStatus } from "@/enums/projectStatus";
|
||||
|
||||
export type T_projects = {
|
||||
name: string;
|
||||
description: string;
|
||||
thumbnail?: string;
|
||||
images?: string[];
|
||||
category: ProjectCategory;
|
||||
githubLink: string;
|
||||
liveLink?: string;
|
||||
technologies: string[];
|
||||
companyName: string;
|
||||
completionYear?: number;
|
||||
isFeatured: boolean;
|
||||
status: ProjectStatus;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export type T_reviews = {
|
||||
rating: number;
|
||||
review: string;
|
||||
client_name: string;
|
||||
thumbnail: string;
|
||||
designation: string;
|
||||
verified_link: string;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
export type T_social_links = {
|
||||
github: string;
|
||||
linkedin?: string;
|
||||
twitter?: string;
|
||||
portfolio?: string;
|
||||
facebook?: string;
|
||||
}
|
||||
|
||||
export type T_team = {
|
||||
name: string;
|
||||
role: string;
|
||||
description: string;
|
||||
image: string;
|
||||
socialLinks: T_social_links;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export const queryKeys = {
|
||||
blogs: ["blogs"],
|
||||
blog: (id: string) => ["blogs", id],
|
||||
|
||||
projects: ["projects"],
|
||||
project: (id: string) => ["projects", id],
|
||||
|
||||
reviews: ["reviews"],
|
||||
review: (id: string) => ["reviews", id],
|
||||
|
||||
team: ["team"],
|
||||
member: (id: string) => ["team", id],
|
||||
};
|
||||
Reference in New Issue
Block a user