update
This commit is contained in:
203
frontEnd/lib/hooks/useAbout.ts
Normal file
203
frontEnd/lib/hooks/useAbout.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
"use client";
|
||||
import { useState, useEffect } from 'react';
|
||||
import { aboutService, AboutPageData, AboutBanner, AboutService, AboutProcess, AboutJourney } from '../api/aboutService';
|
||||
|
||||
interface UseAboutReturn {
|
||||
data: AboutPageData | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
interface UseAboutBannerReturn {
|
||||
data: AboutBanner[] | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
interface UseAboutServiceReturn {
|
||||
data: AboutService[] | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
interface UseAboutProcessReturn {
|
||||
data: AboutProcess[] | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
interface UseAboutJourneyReturn {
|
||||
data: AboutJourney[] | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to fetch all about page data
|
||||
*/
|
||||
export const useAbout = (): UseAboutReturn => {
|
||||
const [data, setData] = useState<AboutPageData | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const result = await aboutService.getAboutPageData();
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
data,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchData,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch about banners
|
||||
*/
|
||||
export const useAboutBanners = (): UseAboutBannerReturn => {
|
||||
const [data, setData] = useState<AboutBanner[] | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const result = await aboutService.getBanners();
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
data,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchData,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch about services
|
||||
*/
|
||||
export const useAboutServices = (): UseAboutServiceReturn => {
|
||||
const [data, setData] = useState<AboutService[] | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const result = await aboutService.getServices();
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
data,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchData,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch about processes
|
||||
*/
|
||||
export const useAboutProcesses = (): UseAboutProcessReturn => {
|
||||
const [data, setData] = useState<AboutProcess[] | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const result = await aboutService.getProcesses();
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
data,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchData,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch about journeys
|
||||
*/
|
||||
export const useAboutJourneys = (): UseAboutJourneyReturn => {
|
||||
const [data, setData] = useState<AboutJourney[] | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const result = await aboutService.getJourneys();
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
data,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchData,
|
||||
};
|
||||
};
|
||||
250
frontEnd/lib/hooks/useBlog.ts
Normal file
250
frontEnd/lib/hooks/useBlog.ts
Normal file
@@ -0,0 +1,250 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import {
|
||||
blogService,
|
||||
BlogPost,
|
||||
BlogPostListResponse,
|
||||
BlogCategory,
|
||||
BlogTag,
|
||||
BlogAuthor
|
||||
} from '../api/blogService';
|
||||
|
||||
// Hook for fetching all blog posts
|
||||
export const useBlogPosts = (params?: {
|
||||
category?: string;
|
||||
tag?: string;
|
||||
author?: number;
|
||||
search?: string;
|
||||
featured?: boolean;
|
||||
ordering?: string;
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
}) => {
|
||||
const [posts, setPosts] = useState<BlogPost[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [pagination, setPagination] = useState<{
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
}>({ count: 0, next: null, previous: null });
|
||||
|
||||
useEffect(() => {
|
||||
const fetchPosts = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await blogService.getPosts(params);
|
||||
setPosts(data.results);
|
||||
setPagination({
|
||||
count: data.count,
|
||||
next: data.next,
|
||||
previous: data.previous
|
||||
});
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
setPosts([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchPosts();
|
||||
}, [params?.category, params?.tag, params?.author, params?.search, params?.page, params?.page_size]);
|
||||
|
||||
return { posts, loading, error, pagination, totalCount: pagination.count };
|
||||
};
|
||||
|
||||
// Hook for fetching a single blog post by slug
|
||||
export const useBlogPost = (slug: string | null) => {
|
||||
const [post, setPost] = useState<BlogPost | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!slug) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchPost = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await blogService.getPostBySlug(slug);
|
||||
setPost(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
setPost(null);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchPost();
|
||||
}, [slug]);
|
||||
|
||||
return { post, loading, error };
|
||||
};
|
||||
|
||||
// Hook for fetching featured blog posts
|
||||
export const useFeaturedPosts = () => {
|
||||
const [posts, setPosts] = useState<BlogPost[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchFeaturedPosts = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await blogService.getFeaturedPosts();
|
||||
setPosts(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
setPosts([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchFeaturedPosts();
|
||||
}, []);
|
||||
|
||||
return { posts, loading, error };
|
||||
};
|
||||
|
||||
// Hook for fetching latest blog posts
|
||||
export const useLatestPosts = (limit: number = 5) => {
|
||||
const [posts, setPosts] = useState<BlogPost[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLatestPosts = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await blogService.getLatestPosts(limit);
|
||||
setPosts(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
setPosts([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchLatestPosts();
|
||||
}, [limit]);
|
||||
|
||||
return { posts, loading, error };
|
||||
};
|
||||
|
||||
// Hook for fetching popular blog posts
|
||||
export const usePopularPosts = (limit: number = 5) => {
|
||||
const [posts, setPosts] = useState<BlogPost[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchPopularPosts = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await blogService.getPopularPosts(limit);
|
||||
setPosts(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
setPosts([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchPopularPosts();
|
||||
}, [limit]);
|
||||
|
||||
return { posts, loading, error };
|
||||
};
|
||||
|
||||
// Hook for fetching blog categories
|
||||
export const useBlogCategories = () => {
|
||||
const [categories, setCategories] = useState<BlogCategory[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await blogService.getCategories();
|
||||
setCategories(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
setCategories([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCategories();
|
||||
}, []);
|
||||
|
||||
return { categories, loading, error };
|
||||
};
|
||||
|
||||
// Hook for fetching blog tags
|
||||
export const useBlogTags = () => {
|
||||
const [tags, setTags] = useState<BlogTag[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTags = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await blogService.getTags();
|
||||
setTags(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
setTags([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchTags();
|
||||
}, []);
|
||||
|
||||
return { tags, loading, error };
|
||||
};
|
||||
|
||||
// Hook for fetching blog authors
|
||||
export const useBlogAuthors = () => {
|
||||
const [authors, setAuthors] = useState<BlogAuthor[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchAuthors = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await blogService.getAuthors();
|
||||
setAuthors(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
setAuthors([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchAuthors();
|
||||
}, []);
|
||||
|
||||
return { authors, loading, error };
|
||||
};
|
||||
|
||||
99
frontEnd/lib/hooks/useCareer.ts
Normal file
99
frontEnd/lib/hooks/useCareer.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { careerService, JobPosition } from '../api/careerService';
|
||||
|
||||
/**
|
||||
* Custom hook to fetch all job positions
|
||||
*/
|
||||
export const useJobs = () => {
|
||||
const [jobs, setJobs] = useState<JobPosition[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchJobs = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await careerService.getAllJobs();
|
||||
setJobs(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchJobs();
|
||||
}, []);
|
||||
|
||||
return { jobs, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom hook to fetch a single job by slug
|
||||
*/
|
||||
export const useJob = (slug: string) => {
|
||||
const [job, setJob] = useState<JobPosition | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🔍 useJob hook called with slug:', slug);
|
||||
|
||||
if (!slug) {
|
||||
console.log('❌ No slug provided, setting loading to false');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchJob = async () => {
|
||||
try {
|
||||
console.log('📡 Fetching job data for slug:', slug);
|
||||
setLoading(true);
|
||||
const data = await careerService.getJobBySlug(slug);
|
||||
console.log('✅ Job data fetched successfully:', data);
|
||||
setJob(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
console.error('❌ Error fetching job data:', err);
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
console.log('🔄 Setting loading to false');
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchJob();
|
||||
}, [slug]);
|
||||
|
||||
return { job, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom hook to fetch featured jobs
|
||||
*/
|
||||
export const useFeaturedJobs = () => {
|
||||
const [jobs, setJobs] = useState<JobPosition[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchFeaturedJobs = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await careerService.getFeaturedJobs();
|
||||
setJobs(data);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchFeaturedJobs();
|
||||
}, []);
|
||||
|
||||
return { jobs, loading, error };
|
||||
};
|
||||
|
||||
340
frontEnd/lib/hooks/useCaseStudy.ts
Normal file
340
frontEnd/lib/hooks/useCaseStudy.ts
Normal file
@@ -0,0 +1,340 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import caseStudyService, {
|
||||
CaseStudy,
|
||||
CaseStudyCategory,
|
||||
Client,
|
||||
CaseStudyListResponse,
|
||||
} from '../api/caseStudyService';
|
||||
|
||||
// Hook to fetch all case studies
|
||||
export const useCaseStudies = (params?: {
|
||||
category?: string;
|
||||
client?: string;
|
||||
search?: string;
|
||||
featured?: boolean;
|
||||
ordering?: string;
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
}) => {
|
||||
const [caseStudies, setCaseStudies] = useState<CaseStudy[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [pagination, setPagination] = useState<{
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
} | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCaseStudies = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getCaseStudies(params);
|
||||
setCaseStudies(data.results);
|
||||
setPagination({
|
||||
count: data.count,
|
||||
next: data.next,
|
||||
previous: data.previous,
|
||||
});
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCaseStudies();
|
||||
}, [
|
||||
params?.category,
|
||||
params?.client,
|
||||
params?.search,
|
||||
params?.featured,
|
||||
params?.ordering,
|
||||
params?.page,
|
||||
params?.page_size,
|
||||
]);
|
||||
|
||||
return { caseStudies, loading, error, pagination };
|
||||
};
|
||||
|
||||
// Hook to fetch a single case study by slug
|
||||
export const useCaseStudy = (slug: string | null) => {
|
||||
const [caseStudy, setCaseStudy] = useState<CaseStudy | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!slug) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchCaseStudy = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getCaseStudyBySlug(slug);
|
||||
setCaseStudy(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCaseStudy();
|
||||
}, [slug]);
|
||||
|
||||
return { caseStudy, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch featured case studies
|
||||
export const useFeaturedCaseStudies = () => {
|
||||
const [featuredCaseStudies, setFeaturedCaseStudies] = useState<CaseStudy[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchFeaturedCaseStudies = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getFeaturedCaseStudies();
|
||||
setFeaturedCaseStudies(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchFeaturedCaseStudies();
|
||||
}, []);
|
||||
|
||||
return { featuredCaseStudies, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch latest case studies
|
||||
export const useLatestCaseStudies = (limit: number = 6) => {
|
||||
const [latestCaseStudies, setLatestCaseStudies] = useState<CaseStudy[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLatestCaseStudies = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getLatestCaseStudies(limit);
|
||||
setLatestCaseStudies(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchLatestCaseStudies();
|
||||
}, [limit]);
|
||||
|
||||
return { latestCaseStudies, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch popular case studies
|
||||
export const usePopularCaseStudies = (limit: number = 6) => {
|
||||
const [popularCaseStudies, setPopularCaseStudies] = useState<CaseStudy[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchPopularCaseStudies = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getPopularCaseStudies(limit);
|
||||
setPopularCaseStudies(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchPopularCaseStudies();
|
||||
}, [limit]);
|
||||
|
||||
return { popularCaseStudies, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch related case studies
|
||||
export const useRelatedCaseStudies = (slug: string | null) => {
|
||||
const [relatedCaseStudies, setRelatedCaseStudies] = useState<CaseStudy[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!slug) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchRelatedCaseStudies = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getRelatedCaseStudies(slug);
|
||||
setRelatedCaseStudies(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchRelatedCaseStudies();
|
||||
}, [slug]);
|
||||
|
||||
return { relatedCaseStudies, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch case study categories
|
||||
export const useCaseStudyCategories = () => {
|
||||
const [categories, setCategories] = useState<CaseStudyCategory[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getCategories();
|
||||
setCategories(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCategories();
|
||||
}, []);
|
||||
|
||||
return { categories, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch categories with case studies
|
||||
export const useCategoriesWithCaseStudies = () => {
|
||||
const [categories, setCategories] = useState<CaseStudyCategory[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getCategoriesWithCaseStudies();
|
||||
setCategories(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCategories();
|
||||
}, []);
|
||||
|
||||
return { categories, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch all clients
|
||||
export const useClients = () => {
|
||||
const [clients, setClients] = useState<Client[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchClients = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getClients();
|
||||
setClients(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchClients();
|
||||
}, []);
|
||||
|
||||
return { clients, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch a single client by slug
|
||||
export const useClient = (slug: string | null) => {
|
||||
const [client, setClient] = useState<Client | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!slug) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchClient = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getClientBySlug(slug);
|
||||
setClient(data);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchClient();
|
||||
}, [slug]);
|
||||
|
||||
return { client, loading, error };
|
||||
};
|
||||
|
||||
// Hook to fetch case studies for a specific client
|
||||
export const useClientCaseStudies = (slug: string | null) => {
|
||||
const [caseStudies, setCaseStudies] = useState<CaseStudy[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!slug) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchClientCaseStudies = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const data = await caseStudyService.getClientCaseStudies(slug);
|
||||
setCaseStudies(data.results);
|
||||
} catch (err) {
|
||||
setError(err as Error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchClientCaseStudies();
|
||||
}, [slug]);
|
||||
|
||||
return { caseStudies, loading, error };
|
||||
};
|
||||
|
||||
128
frontEnd/lib/hooks/usePolicy.ts
Normal file
128
frontEnd/lib/hooks/usePolicy.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
"use client";
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Policy, PolicyListItem, getPolicies, getPolicyByType, getPolicyById } from '../api/policyService';
|
||||
|
||||
interface UsePoliciesReturn {
|
||||
data: PolicyListItem[] | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
interface UsePolicyReturn {
|
||||
data: Policy | null;
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to fetch all policies
|
||||
*/
|
||||
export const usePolicies = (): UsePoliciesReturn => {
|
||||
const [data, setData] = useState<PolicyListItem[] | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const result = await getPolicies();
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
data,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchData,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch a policy by type
|
||||
*/
|
||||
export const usePolicy = (type: 'privacy' | 'terms' | 'support' | null): UsePolicyReturn => {
|
||||
const [data, setData] = useState<Policy | null>(null);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
if (!type) {
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
const result = await getPolicyByType(type);
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err : new Error('An error occurred'));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [type]);
|
||||
|
||||
return {
|
||||
data,
|
||||
isLoading,
|
||||
error,
|
||||
refetch: fetchData,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch a policy by ID
|
||||
*/
|
||||
export const usePolicyById = (id: number | null): UsePolicyReturn => {
|
||||
const [data, setData] = useState<Policy | null>(null);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
const fetchData = async () => {
|
||||
if (!id) {
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
const result = await getPolicyById(id);
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err : new Error('An error occurred'));
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [id]);
|
||||
|
||||
return {
|
||||
data,
|
||||
isLoading,
|
||||
error,
|
||||
refetch: fetchData,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
302
frontEnd/lib/hooks/useServices.ts
Normal file
302
frontEnd/lib/hooks/useServices.ts
Normal file
@@ -0,0 +1,302 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { serviceService, Service, ServiceListResponse, ServiceStats, ServiceSearchResponse } from '../api/serviceService';
|
||||
|
||||
// Hook for fetching all services
|
||||
export const useServices = (params?: {
|
||||
featured?: boolean;
|
||||
category?: string;
|
||||
min_price?: number;
|
||||
max_price?: number;
|
||||
search?: string;
|
||||
ordering?: string;
|
||||
page?: number;
|
||||
}) => {
|
||||
const [services, setServices] = useState<Service[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [pagination, setPagination] = useState<{
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
} | null>(null);
|
||||
|
||||
const fetchServices = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await serviceService.getServices(params);
|
||||
setServices(response.results);
|
||||
setPagination({
|
||||
count: response.count,
|
||||
next: response.next,
|
||||
previous: response.previous,
|
||||
});
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch services');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [params]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchServices();
|
||||
}, [fetchServices]);
|
||||
|
||||
return {
|
||||
services,
|
||||
loading,
|
||||
error,
|
||||
pagination,
|
||||
refetch: fetchServices,
|
||||
};
|
||||
};
|
||||
|
||||
// Hook for fetching a single service by slug
|
||||
export const useService = (slug: string) => {
|
||||
const [service, setService] = useState<Service | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchService = useCallback(async () => {
|
||||
if (!slug) return;
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await serviceService.getServiceBySlug(slug);
|
||||
setService(response);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch service');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [slug]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchService();
|
||||
}, [fetchService]);
|
||||
|
||||
return {
|
||||
service,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchService,
|
||||
};
|
||||
};
|
||||
|
||||
// Hook for fetching featured services
|
||||
export const useFeaturedServices = () => {
|
||||
const [services, setServices] = useState<Service[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchFeaturedServices = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await serviceService.getFeaturedServices();
|
||||
setServices(response.results);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch featured services');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchFeaturedServices();
|
||||
}, [fetchFeaturedServices]);
|
||||
|
||||
return {
|
||||
services,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchFeaturedServices,
|
||||
};
|
||||
};
|
||||
|
||||
// Hook for searching services
|
||||
export const useServiceSearch = (query: string) => {
|
||||
const [results, setResults] = useState<Service[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
const searchServices = useCallback(async (searchQuery: string) => {
|
||||
if (!searchQuery.trim()) {
|
||||
setResults([]);
|
||||
setCount(0);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await serviceService.searchServices(searchQuery);
|
||||
setResults(response.results);
|
||||
setCount(response.count);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to search services');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
searchServices(query);
|
||||
}, 300); // Debounce search
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
}, [query, searchServices]);
|
||||
|
||||
return {
|
||||
results,
|
||||
loading,
|
||||
error,
|
||||
count,
|
||||
search: searchServices,
|
||||
};
|
||||
};
|
||||
|
||||
// Hook for fetching service statistics
|
||||
export const useServiceStats = () => {
|
||||
const [stats, setStats] = useState<ServiceStats | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchStats = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await serviceService.getServiceStats();
|
||||
setStats(response);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch service stats');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchStats();
|
||||
}, [fetchStats]);
|
||||
|
||||
return {
|
||||
stats,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchStats,
|
||||
};
|
||||
};
|
||||
|
||||
// Hook for managing service state (for admin operations)
|
||||
export const useServiceManagement = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const createService = useCallback(async (serviceData: Partial<Service>) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await serviceService.createService(serviceData);
|
||||
return response;
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to create service');
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const updateService = useCallback(async (slug: string, serviceData: Partial<Service>) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await serviceService.updateService(slug, serviceData);
|
||||
return response;
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to update service');
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const deleteService = useCallback(async (slug: string) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
await serviceService.deleteService(slug);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to delete service');
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const uploadServiceImage = useCallback(async (slug: string, imageFile: File) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const response = await serviceService.uploadServiceImage(slug, imageFile);
|
||||
return response;
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to upload service image');
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return {
|
||||
loading,
|
||||
error,
|
||||
createService,
|
||||
updateService,
|
||||
deleteService,
|
||||
uploadServiceImage,
|
||||
};
|
||||
};
|
||||
|
||||
// Hook for navigation services (for header menu)
|
||||
export const useNavigationServices = () => {
|
||||
const [services, setServices] = useState<Service[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchNavigationServices = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
// Fetch only active services, ordered by display_order
|
||||
const response = await serviceService.getServices({
|
||||
ordering: 'display_order',
|
||||
page: 1
|
||||
});
|
||||
// Filter only active services (handle null values as active)
|
||||
const activeServices = response.results.filter(service => service.is_active !== false);
|
||||
setServices(activeServices);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch navigation services');
|
||||
// Set empty array on error to prevent navigation issues
|
||||
setServices([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchNavigationServices();
|
||||
}, [fetchNavigationServices]);
|
||||
|
||||
return {
|
||||
services,
|
||||
loading,
|
||||
error,
|
||||
refetch: fetchNavigationServices,
|
||||
};
|
||||
};
|
||||
251
frontEnd/lib/hooks/useSupport.ts
Normal file
251
frontEnd/lib/hooks/useSupport.ts
Normal file
@@ -0,0 +1,251 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import {
|
||||
getTicketCategories,
|
||||
getTicketStatuses,
|
||||
getTicketPriorities,
|
||||
getKnowledgeBaseCategories,
|
||||
getKnowledgeBaseArticles,
|
||||
getFeaturedArticles,
|
||||
getKnowledgeBaseArticle,
|
||||
getArticlesByCategory,
|
||||
TicketCategory,
|
||||
TicketStatus,
|
||||
TicketPriority,
|
||||
KnowledgeBaseCategory,
|
||||
KnowledgeBaseArticle
|
||||
} from '../api/supportService';
|
||||
|
||||
/**
|
||||
* Hook to fetch ticket categories
|
||||
*/
|
||||
export const useTicketCategories = () => {
|
||||
const [categories, setCategories] = useState<TicketCategory[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getTicketCategories();
|
||||
setCategories(data);
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
setError(err.message || 'Failed to fetch ticket categories');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCategories();
|
||||
}, []);
|
||||
|
||||
return { categories, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch ticket statuses
|
||||
*/
|
||||
export const useTicketStatuses = () => {
|
||||
const [statuses, setStatuses] = useState<TicketStatus[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchStatuses = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getTicketStatuses();
|
||||
setStatuses(data);
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
setError(err.message || 'Failed to fetch ticket statuses');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchStatuses();
|
||||
}, []);
|
||||
|
||||
return { statuses, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch ticket priorities
|
||||
*/
|
||||
export const useTicketPriorities = () => {
|
||||
const [priorities, setPriorities] = useState<TicketPriority[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchPriorities = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getTicketPriorities();
|
||||
setPriorities(data);
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
setError(err.message || 'Failed to fetch ticket priorities');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchPriorities();
|
||||
}, []);
|
||||
|
||||
return { priorities, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch knowledge base categories
|
||||
*/
|
||||
export const useKnowledgeBaseCategories = () => {
|
||||
const [categories, setCategories] = useState<KnowledgeBaseCategory[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getKnowledgeBaseCategories();
|
||||
setCategories(data);
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
setError(err.message || 'Failed to fetch knowledge base categories');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCategories();
|
||||
}, []);
|
||||
|
||||
return { categories, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch knowledge base articles with optional search
|
||||
*/
|
||||
export const useKnowledgeBaseArticles = (search?: string) => {
|
||||
const [articles, setArticles] = useState<KnowledgeBaseArticle[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchArticles = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getKnowledgeBaseArticles(search);
|
||||
setArticles(data);
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
setError(err.message || 'Failed to fetch knowledge base articles');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchArticles();
|
||||
}, [search]);
|
||||
|
||||
return { articles, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch featured knowledge base articles
|
||||
*/
|
||||
export const useFeaturedArticles = () => {
|
||||
const [articles, setArticles] = useState<KnowledgeBaseArticle[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchArticles = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getFeaturedArticles();
|
||||
setArticles(data);
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
setError(err.message || 'Failed to fetch featured articles');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchArticles();
|
||||
}, []);
|
||||
|
||||
return { articles, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch a single knowledge base article
|
||||
*/
|
||||
export const useKnowledgeBaseArticle = (slug: string | null) => {
|
||||
const [article, setArticle] = useState<KnowledgeBaseArticle | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!slug) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchArticle = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getKnowledgeBaseArticle(slug);
|
||||
setArticle(data);
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
setError(err.message || 'Failed to fetch knowledge base article');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchArticle();
|
||||
}, [slug]);
|
||||
|
||||
return { article, loading, error };
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch articles by category
|
||||
*/
|
||||
export const useArticlesByCategory = (categorySlug: string | null) => {
|
||||
const [articles, setArticles] = useState<KnowledgeBaseArticle[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!categorySlug) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchArticles = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getArticlesByCategory(categorySlug);
|
||||
setArticles(data);
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
setError(err.message || 'Failed to fetch articles by category');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchArticles();
|
||||
}, [categorySlug]);
|
||||
|
||||
return { articles, loading, error };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user