Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/staging' into #386-Add-tags-comp…
Browse files Browse the repository at this point in the history
…onent
  • Loading branch information
Jasminamih committed Aug 18, 2024
2 parents a79368c + 8c1cacd commit 97c7c34
Show file tree
Hide file tree
Showing 34 changed files with 991 additions and 365 deletions.
20 changes: 8 additions & 12 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["react", "prettier"],
"plugins": ["react", "prettier", "@typescript-eslint"],
"rules": {
"no-shadow": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-shadow": "error",
"react/jsx-filename-extension": [
1,
{
"extensions": [".jsx", ".tsx"]
}
],

"no-shadow": "off",
"react/react-in-jsx-scope": "off",
"react/no-unescaped-entities": 0,
"@react/no-array-index-key": "off",
Expand All @@ -48,15 +51,7 @@
}
],
"react/require-default-props": "off",
"import/no-cycle": "off",
"no-shadow": "off",
"jsx-a11y/label-has-associated-control": [
"error",
{
"assert": "htmlFor",
"depth": 3
}
]
"import/no-cycle": "off"
},
"settings": {
"react": {
Expand All @@ -78,5 +73,6 @@
"no-unused-vars": "off"
}
}
]
],
"ignorePatterns": ["playwright.config.ts"]
}
23 changes: 23 additions & 0 deletions api/AxiosProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import React, { createContext, useContext } from 'react';
import { AxiosInstance } from 'axios';
import axiosInstanceDefault from './axiosInstance';

const AxiosContext = createContext<AxiosInstance | null>(null);

export const useAxios = () => {
const axiosInstance = useContext(AxiosContext);
if (!axiosInstance) {
throw new Error('useAxios must be used within an AxiosProvider');
}
return axiosInstance;
};

interface AxiosProviderProps {
children: React.ReactNode;
}

export const AxiosProvider = ({ children }: AxiosProviderProps) => {
return <AxiosContext.Provider value={axiosInstanceDefault}>{children}</AxiosContext.Provider>;
};
10 changes: 10 additions & 0 deletions api/axiosInstance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import axios from 'axios';

const axiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_BASE_URL,
headers: {
'Content-Type': 'application/json',
},
});

export default axiosInstance;
23 changes: 23 additions & 0 deletions api/endpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL;

if (!API_BASE_URL) {
throw new Error('NEXT_PUBLIC_API_BASE_URL is not defined in the environment variables');
}

const ENDPOINTS = {
BLOGS: {
GET_ALL: (limit: number, skip: number) => `${API_BASE_URL}/posts?limit=${limit}&skip=${skip}`,
CREATE: `${API_BASE_URL}/posts`,
},
USERS: {
GET_ALL: `${API_BASE_URL}/users`,
},
CONTACT: {
SUBMIT: `${API_BASE_URL}/contact`,
},
NEWSLETTER: {
SUBSCRIBE: `${API_BASE_URL}/newsletter-subscribers`,
},
};

export default ENDPOINTS;
24 changes: 24 additions & 0 deletions api/mutations/blogs/useAddNewPost.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use client';

import { useMutation } from '@tanstack/react-query';
import { useAxios } from '../../AxiosProvider';
import ENDPOINTS from '../../endpoints';

type NewPost = {
title: string;
body: string;
userId: number;
};

const useAddNewPost = () => {
const axios = useAxios();

return useMutation({
mutationFn: async (newPost: NewPost) => {
const response = await axios.post(ENDPOINTS.BLOGS.CREATE, newPost);
return response.data;
},
});
};

export default useAddNewPost;
21 changes: 21 additions & 0 deletions api/mutations/contact/useSubmitContactform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useMutation } from '@tanstack/react-query';
import ENDPOINTS from '../../endpoints';
import { useAxios } from '../../AxiosProvider';

export interface ContactFormData {
name: string;
email: string;
message: string;
cfTurnstileResponse: string;
}

export const useSubmitContactForm = () => {
const axios = useAxios();

return useMutation({
mutationFn: async (formData: ContactFormData) => {
const response = await axios.post(ENDPOINTS.CONTACT.SUBMIT, formData);
return response.data.message;
},
});
};
20 changes: 20 additions & 0 deletions api/mutations/newsletter/useSubmitNewsletterForm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useMutation } from '@tanstack/react-query';
import ENDPOINTS from '../../endpoints';
import { useAxios } from '../../AxiosProvider';

export interface NewsletterFormData {
first_name: string;
email: string;
'cf-turnstile-response': string;
}

export const useSubmitNewsletterForm = () => {
const axios = useAxios();

return useMutation({
mutationFn: async (formData: NewsletterFormData) => {
const response = await axios.post(ENDPOINTS.NEWSLETTER.SUBSCRIBE, formData);
return response.data.message;
},
});
};
17 changes: 17 additions & 0 deletions api/queries/blogs/getBlogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useQuery } from '@tanstack/react-query';
import fetchBlogPosts from '../../../app/action';
import QUERY_KEYS from '../../queryKeys';

interface GetBlogsParams {
pageTitle: string;
blogCardsNumber: number;
}

const useGetBlogs = ({ pageTitle, blogCardsNumber }: GetBlogsParams) => {
return useQuery({
queryKey: [...QUERY_KEYS.BLOGS.ALL, pageTitle, blogCardsNumber],
queryFn: () => fetchBlogPosts(0, blogCardsNumber),
});
};

export default useGetBlogs;
32 changes: 32 additions & 0 deletions api/queries/blogs/getInfiniteBlogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import QUERY_KEYS from '../../queryKeys';
import fetchBlogPosts from '../../../app/action';
import { BlogCardProps } from '../../../components/reusable-components/blog-card/BlogCard';

interface GetInfiniteBlogsParams {
pageTitle: string;
blogCardsNumber: number;
}
const useGetInfiniteBlogs = ({ pageTitle, blogCardsNumber }: GetInfiniteBlogsParams) => {
return useInfiniteQuery<
BlogCardProps[],
Error,
BlogCardProps[],
[string, string, string, string],
number
>({
queryKey: [
QUERY_KEYS.BLOGS.INFINITE[0],
QUERY_KEYS.BLOGS.INFINITE[1],
pageTitle,
blogCardsNumber.toString(),
],
queryFn: ({ pageParam }) => fetchBlogPosts(pageParam, blogCardsNumber),
initialPageParam: 0,
getNextPageParam: (lastPage, allPages) => {
return lastPage.length === blogCardsNumber ? allPages.length * blogCardsNumber : undefined;
},
});
};

export default useGetInfiniteBlogs;
17 changes: 17 additions & 0 deletions api/queries/users/getUsers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useAxios } from '../../AxiosProvider';
import ENDPOINTS from '../../endpoints';
import QUERY_KEYS from '../../queryKeys';

const useGetUsers = () => {
const axios = useAxios();

return {
queryKey: QUERY_KEYS.USERS.ALL,
queryFn: async () => {
const { data } = await axios.get(ENDPOINTS.USERS.GET_ALL);
return data;
},
};
};

export default useGetUsers;
11 changes: 11 additions & 0 deletions api/queryKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const QUERY_KEYS = {
BLOGS: {
ALL: ['blogPosts'],
INFINITE: ['infiniteBlogPosts', 'infinite'] as const,
},
USERS: {
ALL: ['users'],
},
} as const;

export default QUERY_KEYS;
38 changes: 19 additions & 19 deletions app/action.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
'use server';

import BlogCard, { BlogCardProps } from '../components/reusable-components/blog-card/BlogCard';
import axios from 'axios';
import axiosInstance from '../api/axiosInstance';
import { BlogCardProps } from '../components/reusable-components/blog-card/BlogCard';

const fetchBlogPosts = async (nextPosts: number, pageTitle: string, blogCardsNumber: number) => {
const fetchBlogPosts = async (
nextPosts: number,
blogCardsNumber: number
): Promise<BlogCardProps[]> => {
try {
const response = await fetch(
`https://dummyjson.com/posts?limit=${blogCardsNumber}&skip=${nextPosts}`
);

const data = await response.json();

return data?.posts.map((post: BlogCardProps) => {
return (
<BlogCard
key={post?.id}
id={post?.id}
title={post?.title}
body={post?.body}
pageTitle={pageTitle}
/>
);
const { data } = await axiosInstance.get('/posts', {
params: {
limit: blogCardsNumber,
skip: nextPosts,
},
});
return data.posts;
} catch (error: any) {
throw new Error(error);
if (axios.isAxiosError(error)) {
throw new Error(
error.response?.data?.message || 'An error occurred while fetching blog posts'
);
}
throw new Error('An unexpected error occurred');
}
};

Expand Down
52 changes: 0 additions & 52 deletions app/addNewPost.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import BlogList from '../../components/module-components/blog-list/BlogList';
import Tab from '../../components/reusable-components/tab/Tab';
// import AddNewPost from '../addNewPost';
// import AddNewPost from '../../components/module-components/blog/addNewPost';

const Blog = () => {
return (
Expand Down
Loading

0 comments on commit 97c7c34

Please sign in to comment.