tie it all together

This commit is contained in:
2026-09-06 22:51:52 -04:00
parent 4cf612758c
commit 04ad21d4b3
5 changed files with 55 additions and 9 deletions
+7 -3
View File
@@ -1,13 +1,17 @@
import { useAuth } from "../providers/AuthProvider"; import { useAuth } from "../providers/AuthProvider";
import { useNavigate } from "react-router-dom";
export default function Header() { export default function Header() {
const auth = useAuth(); const auth = useAuth();
const navigate = useNavigate();
return ( return (
<div className="flex flex-wrap items-center justify-between gap-x-4 gap-y-1 py-4"> <div className="flex flex-wrap items-center justify-between gap-x-4 gap-y-1 py-4">
<h1 className="font-bold"> <a href="#" onClick={() => navigate("/")}>
Alex <span className="font-normal text-blue-500">/</span> dev + QA <h1 className="font-bold">
</h1> Alex <span className="font-normal text-blue-500">/</span> dev + QA
</h1>
</a>
<div className="flex gap-3 text-sm sm:text-base"> <div className="flex gap-3 text-sm sm:text-base">
{auth.user !== null ? ( {auth.user !== null ? (
<a href="#" onClick={() => auth.logout()}> <a href="#" onClick={() => auth.logout()}>
+3
View File
@@ -3,6 +3,7 @@ type InputType = {
forLabel: string; forLabel: string;
type: "password" | "email" | "text"; type: "password" | "email" | "text";
dark?: boolean; dark?: boolean;
defaultValue?: string;
onChange?: (v: string) => void; onChange?: (v: string) => void;
}; };
@@ -10,6 +11,7 @@ export default function Input({
label, label,
forLabel, forLabel,
type, type,
defaultValue,
dark = true, dark = true,
onChange, onChange,
}: InputType) { }: InputType) {
@@ -23,6 +25,7 @@ export default function Input({
onChange={onChange ? (e) => onChange(e.target.value) : undefined} onChange={onChange ? (e) => onChange(e.target.value) : undefined}
type={type} type={type}
required required
defaultValue={defaultValue}
name={forLabel} name={forLabel}
className={`${dark ? "bg-black text-white" : "bg-white text-black"} rounded-lg border-white block`} className={`${dark ? "bg-black text-white" : "bg-white text-black"} rounded-lg border-white block`}
/> />
+11 -4
View File
@@ -30,8 +30,6 @@ export default function Editor() {
}, []); }, []);
async function createPost() { async function createPost() {
console.log(values);
if (!values?.title || !values.content || !values.description) { if (!values?.title || !values.content || !values.description) {
setError("Missing required value"); setError("Missing required value");
return; return;
@@ -66,7 +64,13 @@ export default function Editor() {
return ( return (
<Layout isProtected={true}> <Layout isProtected={true}>
<h1 className="text-2xl font-bold"> <p
className="text-sm opacity-50 hover:underline hover:cursor-pointer"
onClick={() => history.back()}
>
&lt;- Back
</p>
<h1 className="text-2xl font-bold mb-4">
{editingPost ? "Edit" : "Create"} Post {editingPost ? "Edit" : "Create"} Post
</h1> </h1>
@@ -76,6 +80,7 @@ export default function Editor() {
label="Title" label="Title"
type="text" type="text"
dark={false} dark={false}
defaultValue={editingPost?.title}
onChange={(v) => onChange={(v) =>
setValues((prevState) => { setValues((prevState) => {
return { return {
@@ -88,6 +93,7 @@ export default function Editor() {
<Input <Input
forLabel="description" forLabel="description"
label="Description" label="Description"
defaultValue={editingPost?.description}
type="text" type="text"
dark={false} dark={false}
onChange={(v) => onChange={(v) =>
@@ -131,7 +137,7 @@ export default function Editor() {
/> />
) : ( ) : (
<div className="prose prose-invert"> <div className="prose prose-invert">
<Markdown>{values.content}</Markdown> <Markdown>{values.content || editingPost?.content}</Markdown>
</div> </div>
)} )}
@@ -142,6 +148,7 @@ export default function Editor() {
> >
Submit Submit
</button> </button>
<p className="text-red-300 font-semibold">{error}</p>
</div> </div>
</Layout> </Layout>
); );
+15 -1
View File
@@ -1,11 +1,15 @@
import Layout from "../components/layout"; import Layout from "../components/layout";
import PostRow from "../components/postRow"; import PostRow from "../components/postRow";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useAuth } from "../providers/AuthProvider";
import type { Post } from "../utils/types"; import type { Post } from "../utils/types";
export default function Home() { export default function Home() {
const [posts, setPosts] = useState<Post[] | null>(null); const [posts, setPosts] = useState<Post[] | null>(null);
const [loaded, setLoaded] = useState<boolean>(false); const [loaded, setLoaded] = useState<boolean>(false);
const auth = useAuth();
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
fetch("/api/posts", { fetch("/api/posts", {
@@ -51,7 +55,17 @@ export default function Home() {
</div> </div>
<hr /> <hr />
<div className="mt-2"> <div className="mt-2">
<h1 className="font-semibold">Posts</h1> <div className="flex justify-between">
<h1 className="font-semibold">Posts</h1>
{auth.user && (
<p
className="text-sm opacity-50 hover:cursor-pointer hover:underline"
onClick={() => navigate("/editor")}
>
Create
</p>
)}
</div>
<div className="space-y-2"> <div className="space-y-2">
<PostList /> <PostList />
</div> </div>
+19 -1
View File
@@ -1,12 +1,15 @@
import Layout from "../components/layout"; import Layout from "../components/layout";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useParams } from "react-router-dom"; import { useParams, useNavigate } from "react-router-dom";
import { useAuth } from "../providers/AuthProvider";
import type { Post } from "../utils/types"; import type { Post } from "../utils/types";
import Markdown from "react-markdown"; import Markdown from "react-markdown";
export default function Post() { export default function Post() {
const [post, setPost] = useState<Post | null>(null); const [post, setPost] = useState<Post | null>(null);
const params = useParams(); const params = useParams();
const navigate = useNavigate();
const auth = useAuth();
useEffect(() => { useEffect(() => {
if (params.slug) { if (params.slug) {
@@ -32,6 +35,13 @@ export default function Post() {
return ( return (
<Layout> <Layout>
<div className="my-2"> <div className="my-2">
<a
href="#"
onClick={() => navigate("/")}
className="text-sm opacity-50 hover:underline"
>
&lt;- Home
</a>
<h1 className="text-2xl font-bold">{post.title}</h1> <h1 className="text-2xl font-bold">{post.title}</h1>
<p className="text-sm opacity-50">{post.description}</p> <p className="text-sm opacity-50">{post.description}</p>
@@ -46,6 +56,14 @@ export default function Post() {
{post.updatedAt !== post.createdAt && {post.updatedAt !== post.createdAt &&
"- updated on " + new Date(post.updatedAt).toLocaleString()} "- updated on " + new Date(post.updatedAt).toLocaleString()}
</p> </p>
{auth.user && (
<p
className="text-sm opacity-50 underline hover:cursor-pointer"
onClick={() => navigate(`/editor/${post.slug}`)}
>
Edit
</p>
)}
</div> </div>
</Layout> </Layout>
); );