From 6f06615ef3884bd4ba2e7571189be0f5203aa2c8 Mon Sep 17 00:00:00 2001 From: Shadman Shakib Date: Sun, 18 Aug 2024 21:48:50 -0600 Subject: [PATCH 1/2] Full stack development 3 --- src/api/axiosConfig.js | 34 +++-- src/api/postsApi.js | 2 +- src/components/Card.jsx | 134 +++++++++--------- src/components/CreatePostForm.js | 102 ++++++++++++++ src/components/Header.jsx | 183 +++++++++++++----------- src/lib/formatDate.js | 16 ++- src/pages/index.jsx | 230 +++++++------------------------ src/pages/posts/[slug].jsx | 87 +++++++++--- src/pages/posts/index.jsx | 31 +++-- src/pages/posts/new.js | 178 ++++++++++++++++++++++++ 10 files changed, 623 insertions(+), 374 deletions(-) create mode 100644 src/components/CreatePostForm.js create mode 100644 src/pages/posts/new.js diff --git a/src/api/axiosConfig.js b/src/api/axiosConfig.js index bd45cb2..9a1e5d0 100644 --- a/src/api/axiosConfig.js +++ b/src/api/axiosConfig.js @@ -1,12 +1,30 @@ -import axios from "axios" -import { isHyperlink } from '@/lib/isHyperlink' +import axios from 'axios'; -const BASE_URL = process.env.DOTNET_SERVER_URL +const axiosInstance = axios.create({ + baseURL: process.env.REACT_APP_API_BASE_URL || 'http://localhost:5000/api', + headers: { + 'Content-Type': 'application/json', + }, + timeout: 10000, // Add a timeout to handle long requests +}); -const AXIOS_BASE = axios.create({ - baseURL: BASE_URL, - }) +axiosInstance.interceptors.request.use( + (config) => { + // You can add additional logic here, e.g., attaching tokens + return config; + }, + (error) => { + return Promise.reject(error); + } +); -const JSON_CLIENT = isHyperlink(BASE_URL) ? AXIOS_BASE : false +axiosInstance.interceptors.response.use( + (response) => response, + (error) => { + // You can handle global errors here + return Promise.reject(error); + } +); + +export default axiosInstance; -export default JSON_CLIENT diff --git a/src/api/postsApi.js b/src/api/postsApi.js index 54f8964..6a68a53 100644 --- a/src/api/postsApi.js +++ b/src/api/postsApi.js @@ -20,4 +20,4 @@ export const getPost = (postSlug) => { console.error(e) return {} } -} +} \ No newline at end of file diff --git a/src/components/Card.jsx b/src/components/Card.jsx index 1fdeb9b..f486ae7 100644 --- a/src/components/Card.jsx +++ b/src/components/Card.jsx @@ -1,94 +1,88 @@ -import Link from 'next/link' -import clsx from 'clsx' +import Link from 'next/link'; +import clsx from 'clsx'; +import { formatDate } from '../lib/formatDate'; -function ChevronRightIcon(props) { - return ( - - ) -} +// ChevronRightIcon Component +const ChevronRightIcon = ({ className, ...props }) => ( + +); -export function Card({ as: Component = 'div', className, children }) { - return ( - - {children} - - ) -} +// Card Component +export const Card = ({ as: Component = 'div', className, children }) => ( + + {children} + +); -Card.Link = function CardLink({ children, ...props }) { - return ( - <> -
- - - {children} - - - ) -} +// CardLink Component +export const CardLink = ({ children, ...props }) => ( + <> +
+ + + {children} + + +); -Card.Title = function CardTitle({ as: Component = 'h2', href, children }) { - return ( - - {href ? {children} : children} - - ) -} +// CardTitle Component +export const CardTitle = ({ as: Component = 'h2', href, children }) => ( + + {href ? {children} : children} + +); -Card.Description = function CardDescription({ children }) { - return ( -

- {children} -

- ) -} +// CardDescription Component +export const CardDescription = ({ children }) => ( +

+ {children} +

+); -Card.Cta = function CardCta({ children }) { - return ( - - ) -} +// CardCta Component +export const CardCta = ({ children }) => ( + +); -Card.Eyebrow = function CardEyebrow({ +// CardEyebrow Component +export const CardEyebrow = ({ as: Component = 'p', decorate = false, className, children, + dateTime, ...props -}) { +}) => { + const content = dateTime ? formatDate(dateTime) : children; + return ( {decorate && ( - - ) -} + ); +}; diff --git a/src/components/CreatePostForm.js b/src/components/CreatePostForm.js new file mode 100644 index 0000000..4a79085 --- /dev/null +++ b/src/components/CreatePostForm.js @@ -0,0 +1,102 @@ +import React, { useState } from 'react'; +import { createPost } from '../api/postsApi'; +import { formatDate } from '../lib/formatDate'; + +const CreatePostForm = () => { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [body, setBody] = useState(''); + const [createdDate, setCreatedDate] = useState(new Date()); + const [errors, setErrors] = useState([]); // State to manage errors + + const handleSubmit = async (e) => { + e.preventDefault(); + setErrors([]); // Clear previous errors + + try { + const newPost = { + title, + description, + body, + createdDate: formatDate(createdDate.toISOString()) // Format the date before submission + }; + + const response = await createPost(newPost); + + if (response.status === 201) { + console.log('Post created successfully:', response.data); + // Reset the form after successful submission + setTitle(''); + setDescription(''); + setBody(''); + setCreatedDate(new Date()); // Reset to current date/time + } else { + console.error('Unexpected response:', response); + setErrors(['Unexpected response from the server.']); + } + } catch (error) { + console.error('Error creating post:', error); + + if (error.response) { + console.error('Server Error:', error.response.data); + setErrors(error.response.data.errors || ['An error occurred while creating the post.']); + } else if (error.request) { + console.error('Network Error:', error.request); + setErrors(['Network error: Please check your internet connection.']); + } else { + console.error('Error:', error.message); + setErrors([error.message]); + } + } + }; + + return ( +
+
+ + setTitle(e.target.value)} + required + /> +
+
+ + setDescription(e.target.value)} + required + /> +
+
+ +