Skip to content

Commit

Permalink
Merge pull request #10 from lucasdale99/feature/add-post-creation
Browse files Browse the repository at this point in the history
Feature/add post creation
  • Loading branch information
lucasdale99 authored Nov 13, 2024
2 parents 4ddf9f7 + 492f756 commit f719bcf
Show file tree
Hide file tree
Showing 18 changed files with 103 additions and 125 deletions.
25 changes: 25 additions & 0 deletions actions/blog/getBlog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"use server";

import { eq } from "drizzle-orm";
import { db } from "@/lib/db";
import { blogsTable } from "@/lib/schema";

export async function getBlog(slug: string) {
try {
const incomingSlug = slug.replace(/^\/+|\/+$/g, "");

const blogData = await db
.select()
.from(blogsTable)
.where(eq(blogsTable.slug, `/${incomingSlug}`));

if (!blogData.length) {
throw new Error("Blog not found");
}

return blogData[0];
} catch (error) {
console.error("Error fetching blog:", error);
throw new Error("Failed to fetch blog");
}
}
13 changes: 13 additions & 0 deletions actions/blog/getBlogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use server";
import { db } from "@/lib/db";
import { blogsTable } from "@/lib/schema";

export async function getBlogs() {
try {
const blogs = await db.select().from(blogsTable).execute();
return blogs;
} catch (error) {
console.error("Error fetching blogs:", error);
throw new Error("Failed to fetch blogs");
}
}
18 changes: 18 additions & 0 deletions actions/work/getWorkExperience.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use server";

import { db } from "../../lib/db";
import { workExperienceTable } from "../../lib/schema";

export async function getWorkExperience() {
try {
const workExperience = await db
.select()
.from(workExperienceTable)
.orderBy(workExperienceTable.startDate);

return workExperience;
} catch (error) {
console.error("Error fetching work experience:", error);
throw new Error("Failed to fetch work experience");
}
}
30 changes: 0 additions & 30 deletions app/api/blog/[slug]/route.ts

This file was deleted.

10 changes: 0 additions & 10 deletions app/api/blog/route.ts

This file was deleted.

6 changes: 0 additions & 6 deletions app/api/migration/route.ts

This file was deleted.

17 changes: 4 additions & 13 deletions app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { notFound } from "next/navigation";
import BlogContent from "./components/BlogContent";
import SubscriberForm from "../components/SubscriberForm";
import { getBlog } from "@/actions/blog/getBlog";

interface BlogParams {
params: {
Expand All @@ -9,25 +10,15 @@ interface BlogParams {
}

export default async function BlogPost({ params }: BlogParams) {
const blog = await fetch(
`${process.env.NEXT_PUBLIC_URL}/api/blog/${params.slug}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
}
);

const blogData = await blog.json();
const blog = await getBlog(params.slug);

if (!blogData || !blogData.data) {
if (!blog) {
return notFound();
}

return (
<>
<BlogContent content={blogData.data.content} slug={params.slug} />
<BlogContent content={blog.content} slug={params.slug} />
<div className="flex-1 w-full max-w-4xl mx-auto p-6">
<SubscriberForm />
</div>
Expand Down
6 changes: 3 additions & 3 deletions app/experience/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { workExperience } from "@/data/workExperience";
import { Home } from "lucide-react";
import { getWorkExperience } from "@/actions/work/getWorkExperience";

export default function ExperiencePage() {
const experiences = workExperience;
export default async function ExperiencePage() {
const experiences = await getWorkExperience();
const formatDate = (date: string): string => {
if (date === "Current") return "Present";
return new Date(date).toLocaleDateString("en-US", {
Expand Down
2 changes: 0 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import Image from "next/image";
import Me from "@/public/me.png";
import { TimelineList } from "@/components/TimelineList";
import { AnimatedDescription } from "@/components/AnimatedDescription";
import BlogList from "@/components/BlogList";
import { Card } from "@/components/ui/card";
import BlogCard from "@/components/BlogCard";
export default async function Index() {
const descriptions = [
Expand Down
11 changes: 3 additions & 8 deletions components/BlogList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,15 @@ import { IBlogList } from "@/lib/types";
import BlogCard from "./BlogCard";
import { Suspense } from "react";
import BlogListSkeleton from "./BlogListSkeleton";
import { getBlogs } from "@/actions/blog/getBlogs";

export default async function BlogList() {
const data = await fetch(`${process.env.NEXT_PUBLIC_URL}/api/blog`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const blogs = await data.json();
const blogs = await getBlogs();

return (
<Suspense fallback={<BlogListSkeleton />}>
<div className="flex flex-col">
{blogs.data?.map((blog: IBlogList, index: number) => (
{blogs?.map((blog: IBlogList, index: number) => (
<BlogCard
key={index}
title={blog.title}
Expand Down
7 changes: 4 additions & 3 deletions components/TimelineList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getWorkExperience } from "@/actions/work/getWorkExperience";
import { TimelineCard } from "@/components/TimelineCard";
import { workExperience } from "@/data/workExperience";

interface TimelineItem {
company: string;
Expand All @@ -10,13 +10,14 @@ interface TimelineItem {
slug: string;
}

export const TimelineList: React.FC = () => {
export const TimelineList: React.FC = async () => {
const experiences = await getWorkExperience();
const formatDate = (date: string): string => {
if (date === "Current") return "Current";
return new Date(date).getFullYear().toString();
};

const timelineData: TimelineItem[] = workExperience.map((exp) => ({
const timelineData: TimelineItem[] = experiences.map((exp) => ({
company: exp.company,
startDate: exp.startDate,
endDate: exp.endDate,
Expand Down
39 changes: 0 additions & 39 deletions data/workExperience.ts

This file was deleted.

2 changes: 1 addition & 1 deletion emails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import config from "../tailwind.config";
import Subscribed from "./subscribed";
import Unsubscribed from "./unsubscribed";
export const url = (route: string): string => {
let base = process.env.URL ?? "";
let base = process.env.NEXT_PUBLIC_URL ?? "";
return `${base}${route}`;
};

Expand Down
27 changes: 26 additions & 1 deletion lib/schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { pgTable, serial, uuid, text, timestamp } from "drizzle-orm/pg-core";
import {
pgTable,
serial,
uuid,
text,
timestamp,
varchar,
} from "drizzle-orm/pg-core";
import { sql } from "drizzle-orm";

export const blogsTable = pgTable("blogs_table", {
id: serial("id").primaryKey().notNull(),
Expand All @@ -20,5 +28,22 @@ export const subscribersTable = pgTable("subscribers_table", {
deletedAt: timestamp("deleted_at"),
});

export const workExperienceTable = pgTable("work_experience", {
id: serial("id").primaryKey(),
company: varchar("company", { length: 255 }).notNull(),
position: varchar("position", { length: 255 }).notNull(),
startDate: varchar("start_date", { length: 255 }).notNull(),
endDate: varchar("end_date", { length: 255 }).notNull(),
content: text("content").notNull(),
createdAt: timestamp("created_at")
.default(sql`CURRENT_TIMESTAMP`)
.notNull(),
updatedAt: timestamp("updated_at")
.default(sql`CURRENT_TIMESTAMP`)
.notNull(),
});

export type SelectBlog = typeof blogsTable.$inferSelect;
export type InsertSubscriber = typeof subscribersTable.$inferInsert;
export type WorkExperience = typeof workExperienceTable.$inferSelect;
export type NewWorkExperience = typeof workExperienceTable.$inferInsert;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"dev": "next dev",
"start": "next start",
"deploy": "sst deploy --stage production",
"deploy:stage": "sst deploy --stage staging",
"deploy:staging": "sst deploy --stage staging",
"takeDown": "npx sst remove --stage production",
"generate": "npx drizzle-kit generate",
"db": "sst shell drizzle-kit"
Expand Down
5 changes: 0 additions & 5 deletions sst-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"MyEmail": {
"configSet": string
"sender": string
"type": "sst.aws.Email"
}
"NEXT_PUBLIC_URL": {
"type": "sst.sst.Secret"
"value": string
Expand Down
5 changes: 4 additions & 1 deletion sst.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export default $config({
NEXT_PUBLIC_URL: next_public_url.value,
},
domain: {
name: "letusdev.io",
name:
$app.stage === "production"
? "letusdev.io"
: `${$app.stage}.letusdev.io`,
dns: sst.aws.dns({
zone: "Z0600725332UFN0OF4ISC",
}),
Expand Down
3 changes: 1 addition & 2 deletions utils/email.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { render } from "@react-email/render";
import React from "react";
import { SESv2Client, SendEmailCommand } from "@aws-sdk/client-sesv2";
import { Resource } from "sst";

type ReactComponent =
| React.FunctionComponent<any>
Expand All @@ -26,7 +25,7 @@ export async function mail(template: ReactComponent, mail: MailProps) {
const send = async () =>
await new SESv2Client().send(
new SendEmailCommand({
FromEmailAddress: Resource.MyEmail.sender,
FromEmailAddress: "lucas@strukt.io",
Destination: {
ToAddresses: mail.to || [],
},
Expand Down

0 comments on commit f719bcf

Please sign in to comment.