Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/api/axiosConfig.js
Original file line number Diff line number Diff line change
@@ -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
// Use NEXT_PUBLIC_DOTNET_SERVER_URL for client-side access
const BASE_URL = process.env.NEXT_PUBLIC_DOTNET_SERVER_URL

const AXIOS_BASE = axios.create({
baseURL: BASE_URL,
})
baseURL: BASE_URL,
headers: {
'Content-Type': 'application/json',
},
})

const JSON_CLIENT = isHyperlink(BASE_URL) ? AXIOS_BASE : false
const JSON_CLIENT = isHyperlink(BASE_URL) ? AXIOS_BASE : axios

export default JSON_CLIENT
33 changes: 23 additions & 10 deletions src/api/postsApi.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import API from './axiosConfig'

export const getPosts = () => {
export const getPosts = async () => {
console.log('Posting to URL:', API.defaults.baseURL)
try {
return API.get('/posts/')
.then((res) => res.data)
}
catch (e) {
const res = await API.get('/posts/')
return res.data
} catch (e) {
console.error(e)
return []
}
}

export const getPost = (postSlug) => {
export const getPost = async (postSlug) => {
console.log('Posting to URL:', API.defaults.baseURL)
try {
return API.get(`/posts/${postSlug}`)
.then((res) => res.data)
}
catch (e) {
const res = await API.get(`/posts/${postSlug}`)
return res.data
} catch (e) {
console.error(e)
return {}
}
}
// Added to handle post creation
export const createPost = async (post) => {
console.log("Posting to:", API.defaults.baseURL + '/posts')

console.log('Creating post:', post)
try {
const res = await API.post('/posts', post)
return res.data
} catch (e) {
console.error('Error creating post:', e)
throw e
}
}
17 changes: 15 additions & 2 deletions src/pages/posts/index.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Head from 'next/head'
import Link from 'next/link'

import { Card } from '@/components/Card'
import { SimpleLayout } from '@/components/SimpleLayout'
import { formatDate } from '@/lib/formatDate'
import { getPosts, getPost } from "@/api/postsApi"
import { getPosts } from "@/api/postsApi"

function Post({ post }) {
const date = new Date(post.createdDate)
Expand Down Expand Up @@ -51,21 +52,33 @@ export default function PostsIndex({ posts }) {
intro="All of my long-form thoughts on programming, leadership, product design, and more, collected in chronological order."
>
<div className="md:border-l md:border-zinc-100 md:pl-6">

<div className="flex max-w-3xl flex-col space-y-16">
{posts.map((post) => (
<Post key={post.slug} post={post} />
))}
</div>
<div className="flex mb-6">
<Link
href="/posts/new"
className="inline-block rounded-md bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700"
>
Create Post
</Link>
</div>
</div>
</SimpleLayout>
</>
)
}

export async function getStaticProps() {
const posts = await getPosts() || []
console.log("Fetched posts:", posts)

return {
props: {
posts: (await getPosts() || []),
posts,
},
}
}
88 changes: 88 additions & 0 deletions src/pages/posts/new.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import Head from 'next/head'
import { useState } from 'react'
import { useRouter } from 'next/router'

import { Card } from '@/components/Card'
import { SimpleLayout } from '@/components/SimpleLayout'

import { createPost } from '@/api/postsApi'

export default function CreatePostPage() {
const router = useRouter()

const [title, setTitle] = useState('')
const [body, setBody] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)

const handleSubmit = async (e) => {
e.preventDefault()
setLoading(true)
setError(null)
console.log('Creating post:', { title, body })
try {
const newPost = await createPost({ title, body })
if (newPost?.slug) {
await router.push(`/posts/${newPost.slug}`)
} else {
throw new Error('No slug returned from API')
}
} catch (err) {
console.error(err)
setError("Failed to create post")
} finally {
setLoading(false)
}
}

return (
<>
<Head>
<title>Create Post - Spencer Sharp</title>
<meta name="description" content="Write and publish a new post." />
</Head>

<SimpleLayout
title="Create a new post"
intro="Use the form below to write and publish a new post."
>
<div className="max-w-7xl mx-auto px-6 space-y-6 w-full">
<Card>
<form onSubmit={handleSubmit} className="space-y-6 w-full">
<div className="w-full">
<label className="block text-sm font-medium text-zinc-700">Title</label>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
className="mt-1 block w-full rounded-md border border-zinc-300 px-3 py-2 text-base shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
required
/>
</div>

<div className="w-full">
<label className="block text-sm font-medium text-zinc-700">Body</label>
<textarea
value={body}
onChange={(e) => setBody(e.target.value)}
className="mt-1 block w-full rounded-md border border-zinc-300 px-3 py-2 h-60 text-base shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
required
/>
</div>

{error && <p className="text-sm text-red-600">{error}</p>}

<button
type="submit"
className="inline-flex items-center px-4 py-2 rounded-md bg-indigo-600 text-white text-sm font-medium hover:bg-indigo-700 min-w-[140px]"
disabled={loading}
>
{loading ? 'Submitting...' : 'Create Post'}
</button>
</form>
</Card>
</div>
</SimpleLayout>
</>
)
}