diff --git a/src/api/axiosConfig.js b/src/api/axiosConfig.js index bd45cb2..2e9d487 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 +// Define base URL and headers in environment variables +const BASE_URL = process.env.API_BASE_URL || 'http://localhost:5000/api'; -const AXIOS_BASE = axios.create({ - baseURL: BASE_URL, - }) +// Create Axios instance with predefined configuration +const axiosInstance = axios.create({ + baseURL: BASE_URL, + headers: { + 'Content-Type': 'application/json', + }, +}); -const JSON_CLIENT = isHyperlink(BASE_URL) ? AXIOS_BASE : false +// Optional: Add interceptors if needed for requests and responses +// axiosInstance.interceptors.request.use(config => { +// // Modify request config if needed (e.g., add authentication tokens) +// return config; +// }, error => { +// return Promise.reject(error); +// }); -export default JSON_CLIENT +// axiosInstance.interceptors.response.use(response => { +// // Modify response data if needed +// return response; +// }, error => { +// // Handle response errors +// return Promise.reject(error); +// }); + +export default axiosInstance; diff --git a/src/api/postsApi.js b/src/api/postsApi.js index 54f8964..42f6216 100644 --- a/src/api/postsApi.js +++ b/src/api/postsApi.js @@ -1,23 +1,51 @@ -import API from './axiosConfig' +const apiUrl = process.env.DOTNET_SERVER_URL || 'http://localhost:5000'; -export const getPosts = () => { +// Helper function for API requests +const fetchApi = async (endpoint, options = {}) => { try { - return API.get('/posts/') - .then((res) => res.data) - } - catch (e) { - console.error(e) - return [] - } -} + const url = `${apiUrl}${endpoint}`; + console.log(`Fetching URL: ${url}`); + console.log('Options:', options); -export const getPost = (postSlug) => { - try { - return API.get(`/posts/${postSlug}`) - .then((res) => res.data) - } - catch (e) { - console.error(e) - return {} + const response = await fetch(url, options); + + if (!response.ok) { + let errorDetails = 'No error details available.'; + try { + // Try to parse the error details from the response body + errorDetails = await response.text(); + } catch (err) { + // If parsing fails, keep the default message + console.error('Error details parsing failed:', err); + } + throw new Error(`Error ${options.method || 'GET'} ${endpoint}: ${response.status} ${response.statusText} - ${errorDetails}`); + } + + try { + // Try to parse the JSON response + return await response.json(); + } catch (err) { + // If JSON parsing fails, fall back to plain text + console.warn('Response is not JSON, returning text:', err); + return response.text(); + } + } catch (error) { + console.error(`Error during ${options.method || 'GET'} request to ${endpoint}:`, error); + throw error; } -} +}; + +// Fetch all posts +export const getPosts = () => fetchApi('/api/posts'); + +// Fetch a single post by slug +export const getPost = (slug) => fetchApi(`/api/posts/${slug}`); + +// Create a new post +export const createPost = (post) => fetchApi('/api/posts', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(post), +}); diff --git a/src/components/CreatePostForm.js b/src/components/CreatePostForm.js new file mode 100644 index 0000000..cdf0553 --- /dev/null +++ b/src/components/CreatePostForm.js @@ -0,0 +1,106 @@ +import React, { useState } from 'react'; +import { useRouter } from 'next/router'; +import { createPost } from '../api/postsApi'; + +const CreatePostForm = () => { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [body, setBody] = useState(''); + const router = useRouter(); + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + const newPost = { title, description, body }; + const response = await createPost(newPost); + console.log('Post created successfully:', response); + + // Redirect to the posts page or the newly created post's page + router.push('/posts'); // or use `router.push(`/posts/${response.data.slug}`) if your API returns a slug + } catch (error) { + console.error('Error creating post:', error); + } + }; + + return ( +
+ ); +}; + +const styles = { + form: { + maxWidth: '600px', + margin: '0 auto', + padding: '20px', + borderRadius: '8px', + backgroundColor: '#f9f9f9', + boxShadow: '0px 0px 10px rgba(0, 0, 0, 0.1)', + }, + formGroup: { + marginBottom: '15px', + }, + label: { + display: 'block', + marginBottom: '5px', + fontWeight: 'bold', + }, + input: { + width: '100%', + padding: '10px', + fontSize: '16px', + borderRadius: '4px', + border: '1px solid #ccc', + boxSizing: 'border-box', + }, + textarea: { + width: '100%', + padding: '10px', + fontSize: '16px', + borderRadius: '4px', + border: '1px solid #ccc', + boxSizing: 'border-box', + minHeight: '100px', + }, + button: { + padding: '10px 20px', + fontSize: '16px', + color: '#fff', + backgroundColor: '#007bff', + border: 'none', + borderRadius: '4px', + cursor: 'pointer', + }, +}; + +export default CreatePostForm; \ No newline at end of file diff --git a/src/components/Header.jsx b/src/components/Header.jsx index b90f29e..db049bb 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -1,122 +1,128 @@ -import { Fragment, useEffect, useRef } from 'react' -import Image from 'next/image' -import Link from 'next/link' -import { useRouter } from 'next/router' -import { Popover, Transition } from '@headlessui/react' -import clsx from 'clsx' - -import { Container } from '@/components/Container' -import LoginLogoutLink from "@/components/LoginLogoutLink" -import avatarImage from '@/images/avatar.jpg' - -function CloseIcon(props) { - return ( - - ) -} +import { Fragment, useEffect, useRef } from 'react'; +import Image from 'next/image'; +import Link from 'next/link'; +import { useRouter } from 'next/router'; +import { Popover, Transition } from '@headlessui/react'; +import clsx from 'clsx'; + +import { Container } from '@/components/Container'; +import LoginLogoutLink from '@/components/LoginLogoutLink'; +import CreatePostForm from './CreatePostForm'; +import avatarImage from '@/images/avatar.jpg'; + +// Icons +const CloseIcon = (props) => ( + +); + +const ChevronDownIcon = (props) => ( + +); -function ChevronDownIcon(props) { - return ( - - ) -} +// Mobile Navigation Item +const MobileNavItem = ({ href, children }) => { + const router = useRouter(); + const isActive = router.pathname === href; -function MobileNavItem({ href, children }) { return ({error}
; + if (!post) returnLoading...
; + + const formattedDate = new Date(post.createdDate).toLocaleDateString(); const meta = { author: 'Spencer Sharp', date: post.createdDate, title: post.title, description: post.body, - } + }; return ({post.body}
+Created on: {formattedDate}
+