From cfcde13f3830f410b066c59bfe8117e0c0d3fca6 Mon Sep 17 00:00:00 2001 From: numanm4 Date: Mon, 5 Aug 2024 09:28:31 -0600 Subject: [PATCH 1/3] adding create-post page content and Navigation --- package-lock.json | 16 +++---- package.json | 2 +- src/api/axiosConfig.js | 9 +++- src/components/Header.jsx | 45 +++++++++++++++++ src/pages/posts/create-post.jsx | 85 +++++++++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 src/pages/posts/create-post.jsx diff --git a/package-lock.json b/package-lock.json index 1e1c817..7d069ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@next/mdx": "^13.0.2", "@tailwindcss/typography": "^0.5.4", "autoprefixer": "^10.4.12", - "axios": "^1.2.0", + "axios": "^1.7.3", "clsx": "^2.0.0", "fast-glob": "^3.2.11", "feed": "^4.2.2", @@ -1363,11 +1363,11 @@ } }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", + "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3237,9 +3237,9 @@ "integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==" }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", diff --git a/package.json b/package.json index a26b950..a6800b9 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "@next/mdx": "^13.0.2", "@tailwindcss/typography": "^0.5.4", "autoprefixer": "^10.4.12", - "axios": "^1.2.0", + "axios": "^1.7.3", "clsx": "^2.0.0", "fast-glob": "^3.2.11", "feed": "^4.2.2", diff --git a/src/api/axiosConfig.js b/src/api/axiosConfig.js index bd45cb2..0e94dea 100644 --- a/src/api/axiosConfig.js +++ b/src/api/axiosConfig.js @@ -1,12 +1,17 @@ import axios from "axios" import { isHyperlink } from '@/lib/isHyperlink' -const BASE_URL = process.env.DOTNET_SERVER_URL + +const BASE_URL = process.env.DOTNET_SERVER_URL || 'https://localhost:5000/api'; + const AXIOS_BASE = axios.create({ baseURL: BASE_URL, - }) + timeout: 1000, + }); + const JSON_CLIENT = isHyperlink(BASE_URL) ? AXIOS_BASE : false + export default JSON_CLIENT diff --git a/src/components/Header.jsx b/src/components/Header.jsx index b90f29e..cb51f41 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -5,10 +5,12 @@ 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 (
  • @@ -48,6 +52,7 @@ function MobileNavItem({ href, children }) { ) } + function MobileNavigation(props) { return ( @@ -92,6 +97,11 @@ function MobileNavigation(props) {
      About Posts +
    • + + Create Post + +
    • Projects Speaking Uses @@ -105,9 +115,11 @@ function MobileNavigation(props) { ) } + function NavItem({ href, children }) { let isActive = useRouter().pathname === href + return (
      • About Posts +
      • + + Create Post + +
      • Projects Speaking Uses @@ -143,12 +163,14 @@ function DesktopNavigation(props) { ) } + function clamp(number, a, b) { let min = Math.min(a, b) let max = Math.max(a, b) return Math.min(Math.max(number, min), max) } + function AvatarContainer({ className, ...props }) { return (
        { let downDelay = avatarRef.current?.offsetTop ?? 0 let upDelay = 64 + function setProperty(property, value) { document.documentElement.style.setProperty(property, value) } + function removeProperty(property) { document.documentElement.style.removeProperty(property) } + function updateHeaderStyles() { let { top, height } = headerRef.current.getBoundingClientRect() let scrollY = clamp( @@ -210,12 +239,15 @@ export function Header() { document.body.scrollHeight - window.innerHeight ) + if (isInitial.current) { setProperty('--header-position', 'sticky') } + setProperty('--content-offset', `${downDelay}px`) + if (isInitial.current || scrollY < downDelay) { setProperty('--header-height', `${downDelay + height}px`) setProperty('--header-mb', `${-downDelay}px`) @@ -228,6 +260,7 @@ export function Header() { setProperty('--header-mb', `${-scrollY}px`) } + if (top === 0 && scrollY > 0 && scrollY >= downDelay) { setProperty('--header-inner-position', 'fixed') removeProperty('--header-top') @@ -239,53 +272,65 @@ export function Header() { } } + function updateAvatarStyles() { if (!isHomePage) { return } + let fromScale = 1 let toScale = 36 / 64 let fromX = 0 let toX = 2 / 16 + let scrollY = downDelay - window.scrollY + let scale = (scrollY * (fromScale - toScale)) / downDelay + toScale scale = clamp(scale, fromScale, toScale) + let x = (scrollY * (fromX - toX)) / downDelay + toX x = clamp(x, fromX, toX) + setProperty( '--avatar-image-transform', `translate3d(${x}rem, 0, 0) scale(${scale})` ) + let borderScale = 1 / (toScale / scale) let borderX = (-toX + x) * borderScale let borderTransform = `translate3d(${borderX}rem, 0, 0) scale(${borderScale})` + setProperty('--avatar-border-transform', borderTransform) setProperty('--avatar-border-opacity', scale === toScale ? 1 : 0) } + function updateStyles() { updateHeaderStyles() updateAvatarStyles() isInitial.current = false } + updateStyles() window.addEventListener('scroll', updateStyles, { passive: true }) window.addEventListener('resize', updateStyles) + return () => { window.removeEventListener('scroll', updateStyles, { passive: true }) window.removeEventListener('resize', updateStyles) } }, [isHomePage]) + return ( <>
        { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [errors, setErrors] = useState(''); + const router = useRouter(); + + + const handleSubmit = async (e) => { + e.preventDefault(); + setErrors({}); + + + try { + const response = await JSON_CLIENT.post('http://localhost:3000/posts/create-post', {title, description}); + router.push('/create-post/${reesponse.data.id}'); + } + catch (errors) { + if (errors.response && error.responsse.data) { + setErrors(error.response.data.errors); + } + else{ + setErrors({ form: 'an unexpected error has occured'}); + } + } + }; + + +return ( + +

        + Create New Post +

        +
        +
        + + setTitle(e.target.value)} + className = 'block w-full p-2 mt-1 border border-zinc-300 rounded-md shadow-sm0' + /> + {errors.title &&

        {errors.title}

        } +
        +
        + + setDescription(e.target.value)} + className="block w-full p-2 mt-1 border border-zinc-300 rounded-md shadow-sm" + /> + {errors.description &&

        {errors.description}

        } +
        +
        + + {errors.form &&

        {errors.form}

        } +
        +
        +
        +); +}; + + +export default NewPost; \ No newline at end of file From c95c97f6580c4043c6cf5631bacfbd00b1f3c6af Mon Sep 17 00:00:00 2001 From: numanm4 Date: Wed, 7 Aug 2024 14:40:57 -0600 Subject: [PATCH 2/3] frontend done --- src/api/axiosConfig.js | 2 +- src/api/postsApi.js | 32 ++++----- src/pages/posts/[slug].jsx | 12 ++-- src/pages/posts/create-post.jsx | 119 +++++++++++++++----------------- 4 files changed, 76 insertions(+), 89 deletions(-) diff --git a/src/api/axiosConfig.js b/src/api/axiosConfig.js index 0e94dea..531432a 100644 --- a/src/api/axiosConfig.js +++ b/src/api/axiosConfig.js @@ -2,7 +2,7 @@ import axios from "axios" import { isHyperlink } from '@/lib/isHyperlink' -const BASE_URL = process.env.DOTNET_SERVER_URL || 'https://localhost:5000/api'; +const BASE_URL = process.env.DOTNET_SERVER_URL || 'http://localhost:5000/api'; const AXIOS_BASE = axios.create({ diff --git a/src/api/postsApi.js b/src/api/postsApi.js index 54f8964..4a478e9 100644 --- a/src/api/postsApi.js +++ b/src/api/postsApi.js @@ -1,23 +1,21 @@ -import API from './axiosConfig' +import JSON_CLIENT from '@/api/axiosConfig'; -export const getPosts = () => { +export const getPosts = async () => { try { - return API.get('/posts/') - .then((res) => res.data) + const response = await JSON_CLIENT.get('/posts'); + return response.data; + } catch (error) { + console.error('Failed to fetch posts:', error); + return []; } - catch (e) { - console.error(e) - return [] - } -} +}; -export const getPost = (postSlug) => { +export const getPost = async (slug) => { try { - return API.get(`/posts/${postSlug}`) - .then((res) => res.data) - } - catch (e) { - console.error(e) - return {} + const response = await JSON_CLIENT.get(`/posts/${slug}`); + return response.data; + } catch (error) { + console.error('Failed to fetch post:', error); + return null; } -} +}; diff --git a/src/pages/posts/[slug].jsx b/src/pages/posts/[slug].jsx index b71f258..f7c22b8 100644 --- a/src/pages/posts/[slug].jsx +++ b/src/pages/posts/[slug].jsx @@ -3,10 +3,8 @@ import { getPost, getPosts } from "@/api/postsApi" import { postParameters } from "@/lib/postUtilities" export async function getStaticPaths() { - const posts = await getPosts() - - const postParams = posts ? postParameters(posts) : [] - + const posts = await getPosts(); + const postParams = posts ? postParameters(posts) : []; return { paths: postParams, fallback: false, @@ -14,21 +12,19 @@ export async function getStaticPaths() { } export async function getStaticProps(context) { - const currentPost = await getPost(context.params.slug) - + const currentPost = await getPost(context.params.slug); return { props: { post: currentPost || {} }, } } export default function Post({ post }) { - const meta = { author: 'Spencer Sharp', date: post.createdDate, title: post.title, description: post.body, - } + }; return ( diff --git a/src/pages/posts/create-post.jsx b/src/pages/posts/create-post.jsx index 1f9fb35..5aa17f5 100644 --- a/src/pages/posts/create-post.jsx +++ b/src/pages/posts/create-post.jsx @@ -3,83 +3,76 @@ import { useRouter } from 'next/router'; import JSON_CLIENT from '@/api/axiosConfig'; import { Container } from '@/components/Container'; - const NewPost = () => { const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); - const [errors, setErrors] = useState(''); + const [errors, setErrors] = useState({}); const router = useRouter(); - const handleSubmit = async (e) => { e.preventDefault(); setErrors({}); - try { - const response = await JSON_CLIENT.post('http://localhost:3000/posts/create-post', {title, description}); - router.push('/create-post/${reesponse.data.id}'); - } - catch (errors) { - if (errors.response && error.responsse.data) { + const response = await JSON_CLIENT.post('http://localhost:5000/posts/create-post', { title, description }); + router.push(`/posts/${response.data.slug}`); + } catch (error) { + if (error.response && error.response.data) { setErrors(error.response.data.errors); - } - else{ - setErrors({ form: 'an unexpected error has occured'}); + } else { + setErrors({ form: 'An unexpected error has occurred' }); } } }; - -return ( - -

        - Create New Post -

        -
        -
        - - setTitle(e.target.value)} - className = 'block w-full p-2 mt-1 border border-zinc-300 rounded-md shadow-sm0' - /> - {errors.title &&

        {errors.title}

        } -
        -
        - - setDescription(e.target.value)} - className="block w-full p-2 mt-1 border border-zinc-300 rounded-md shadow-sm" - /> - {errors.description &&

        {errors.description}

        } -
        -
        - - {errors.form &&

        {errors.form}

        } -
        -
        -
        -); + return ( + +

        + Create New Post +

        +
        +
        + + setTitle(e.target.value)} + className="block w-full p-2 mt-1 border border-zinc-300 rounded-md shadow-sm" + /> + {errors.title &&

        {errors.title}

        } +
        +
        + + setDescription(e.target.value)} + className="block w-full p-2 mt-1 border border-zinc-300 rounded-md shadow-sm" + /> + {errors.description &&

        {errors.description}

        } +
        +
        + + {errors.form &&

        {errors.form}

        } +
        +
        +
        + ); }; - -export default NewPost; \ No newline at end of file +export default NewPost; From 83338e2cbe6bb7d0f2eb93852a8ec3c7cab70a1e Mon Sep 17 00:00:00 2001 From: numanm4 Date: Thu, 8 Aug 2024 14:01:23 -0600 Subject: [PATCH 3/3] bug fixes --- src/pages/posts/[slug].jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/posts/[slug].jsx b/src/pages/posts/[slug].jsx index f7c22b8..d4fe0c3 100644 --- a/src/pages/posts/[slug].jsx +++ b/src/pages/posts/[slug].jsx @@ -18,10 +18,11 @@ export async function getStaticProps(context) { } } + export default function Post({ post }) { const meta = { author: 'Spencer Sharp', - date: post.createdDate, + date: post.createdDate, //bug fixes title: post.title, description: post.body, };