Next.js application using TypeScript and Prisma Blog

Jun 04, 202488 mins read

blogging-428954-1280.jpg

1. Define Prisma Schema
Ensure your Prisma schema includes a model for Blog.

// schema.prisma
model Blog {
  id        Int      @id @default(autoincrement())
  title     String
  content   String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

 

2. Create Controller Function
Implement a controller function to handle fetching and searching blogs with pagination. Place this in a file like controllers/blogController.ts.

// controllers/blogController.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export async function getBlogs(search: string | null = null, page: number = 1, pageSize: number = 15) {
  const skip = (page - 1) * pageSize;
  const where = search
    ? { title: { contains: search, mode: 'insensitive' } }
    : {};

  const blogs = await prisma.blog.findMany({
    where,
    orderBy: { createdAt: 'desc' },
    skip,
    take: pageSize,
  });

  const totalBlogs = await prisma.blog.count({ where });

  return {
    blogs,
    totalPages: Math.ceil(totalBlogs / pageSize),
    currentPage: page,
  };
}

 

3. Set up API Route
Create an API route to handle the GET request for fetching and searching blogs with pagination. Place this in pages/api/blogs.ts.

// pages/api/blogs.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { getBlogs } from '@/app/server/controllers/blogController';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'GET') {
    const { search, page = '1' } = req.query;

    try {
      const blogs = await getBlogs(
        search ? String(search) : null,
        parseInt(page as string, 10)
      );
      res.status(200).json(blogs);
    } catch (error) {
      console.error(error);
      res.status(500).json({ error: 'Internal Server Error' });
    }
  } else {
    res.setHeader('Allow', ['GET']);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

 

4. Create View (Next.js Page)
Implement a Next.js page to display and search blogs with pagination. Place this in pages/blogs/index.tsx.

// pages/blogs/index.tsx
import { useState, useEffect } from 'react';
import axios from 'axios';
import { useRouter } from 'next/router';

const BlogsPage = () => {
  const [blogs, setBlogs] = useState([]);
  const [search, setSearch] = useState('');
  const [sortSearch, setSortSearch] = useState('');
  const [totalPages, setTotalPages] = useState(1);
  const [currentPage, setCurrentPage] = useState(1);

  const router = useRouter();
  const { page } = router.query;

  useEffect(() => {
    fetchBlogs();
  }, [sortSearch, page]);

  const fetchBlogs = async () => {
    try {
      const response = await axios.get('/api/blogs', {
        params: { search: sortSearch, page: page || 1 },
      });
      setBlogs(response.data.blogs);
      setTotalPages(response.data.totalPages);
      setCurrentPage(response.data.currentPage);
    } catch (error) {
      console.error('Error fetching blogs:', error);
    }
  };

  const handleSearch = (e: React.FormEvent) => {
    e.preventDefault();
    setSortSearch(search);
    router.push('/blogs?page=1');
  };

  const handlePageChange = (newPage: number) => {
    router.push(`/blogs?page=${newPage}`);
  };

  return (
    <div>
      <h1>Blogs</h1>
      <form onSubmit={handleSearch}>
        <input
          type=text
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder="Search blogs"
        />
        <button type=submit>Search</button>
      </form>
      <ul>
        {blogs.map((blog: { id: number, title: string }) => (
          <li key={blog.id}>{blog.title}</li>
        ))}
      </ul>
      <div>
        {Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => (
          <button
            key={page}
            onClick={() => handlePageChange(page)}
            disabled === page}
          >
            {page}
          </button>
        ))}
      </div>
    </div>
  );
};

export default BlogsPage;

 

Summary
Controller: The getBlogs function in controllers/blogController.ts handles fetching and searching blogs with pagination.
API Route: The API route in pages/api/blogs.ts handles the GET request for fetching and searching blogs with pagination.
View: The form and pagination controls in pages/blogs/index.tsx allow users to search and navigate through the blogs.
This setup ensures that your Next.js application can handle fetching and searching blogs with pagination while maintaining a clean MVC structure. Adjust the code as needed to fit your specific requirements.

Next.js application using TypeScript and Prisma, you need to handle fetching and searching blogs

1. Define Prisma Schema
Ensure your Prisma schema includes a model for Blog.

// schema.prisma
model Blog {
  id        Int      @id @default(autoincrement())
  title     String
  content   String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

 

2. Create Controller Function
Implement a controller function to handle fetching and searching blogs. Place this in a file like controllers/blogController.ts.

// controllers/blogController.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export async function getBlogs(search: string | null = null) {
  const where = search
    ? { title: { contains: search, mode: 'insensitive' } }
    : {};

  return prisma.blog.findMany({
    where,
    orderBy: { createdAt: 'desc' },
  });
}

 

3. Set up API Route
Create an API route to handle the GET request for fetching and searching blogs. Place this in pages/api/blogs.ts.

// pages/api/blogs.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { getBlogs } from '@/app/server/controllers/blogController';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'GET') {
    const { search } = req.query;

    try {
      const blogs = await getBlogs(search ? String(search) : null);
      res.status(200).json({ blogs });
    } catch (error) {
      console.error(error);
      res.status(500).json({ error: 'Internal Server Error' });
    }
  } else {
    res.setHeader('Allow', ['GET']);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

 

4. Create View (Next.js Page)
Implement a Next.js page to display and search blogs. Place this in pages/blogs/index.tsx.

// pages/blogs/index.tsx
import { useState, useEffect } from 'react';
import axios from 'axios';

const BlogsPage = () => {
  const [blogs, setBlogs] = useState([]);
  const [search, setSearch] = useState('');
  const [sortSearch, setSortSearch] = useState('');

  useEffect(() => {
    fetchBlogs();
  }, [sortSearch]);

  const fetchBlogs = async () => {
    try {
      const response = await axios.get('/api/blogs', {
        params: { search: sortSearch },
      });
      setBlogs(response.data.blogs);
    } catch (error) {
      console.error('Error fetching blogs:', error);
    }
  };

  const handleSearch = (e: React.FormEvent) => {
    e.preventDefault();
    setSortSearch(search);
  };

  return (
    <div>
      <h1>Blogs</h1>
      <form onSubmit={handleSearch}>
        <input
          type=text
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder="Search blogs"
        />
        <button type=submit>Search</button>
      </form>
      <ul>
        {blogs.map((blog: { id: number; title: string }) => (
          <li key={blog.id}>{blog.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default BlogsPage;

 

Summary
Controller: The getBlogs function in controllers/blogController.ts handles fetching and searching blogs.
API Route: The API route in pages/api/blogs.ts handles the GET request for fetching and searching blogs.
View: The form in pages/blogs/index.tsx allows users to search for blogs and displays the results.
This setup ensures that your Next.js application can handle fetching and searching blogs while maintaining a clean MVC structure. Adjust the code as needed to fit your specific requirements.

Next.js application using TypeScript and Prisma, you need to handle form submission, validate the input, create a new blog post, and save it to the database

1. Define Prisma Schema
Ensure your Prisma schema includes a model for Blog.

// schema.prisma
model Blog {
  id                Int      @id @default(autoincrement())
  category_id       Int
  title             String
  banner            String
  slug              String
  short_description String
  description       String
  meta_title        String
  meta_img          String
  meta_description  String
  meta_keywords     String
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt

  // Add a relation to the BlogCategory model if necessary
  category          BlogCategory @relation(fields: [category_id], references: [id])
}

 

2. Create Controller Function
Implement a controller function to handle creating a new blog post. Place this in a file like controllers/blogController.ts.

// controllers/blogController.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export async function createBlogPost(data: any) {
  const slug = data.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');

  return prisma.blog.create({
    data: {
      category: { connect: { id: data.category_id } },
      title: data.title,
      banner: data.banner,
      slug,
      short_description: data.short_description,
      description: data.description,
      meta_title: data.meta_title,
      meta_img: data.meta_img,
      meta_description: data.meta_description,
      meta_keywords: data.meta_keywords,
    },
  });
}

 

3. Set up API Route
Create an API route to handle the POST request for creating a new blog post. Place this in pages/api/blogs.ts.

// pages/api/blogs.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { createBlogPost } from '@/app/server/controllers/blogController';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'POST') {
    try {
      const blog = await createBlogPost(req.body);
      res.status(201).json({ blog });
    } catch (error) {
      console.error(error);
      res.status(500).json({ error: 'Internal Server Error' });
    }
  } else {
    res.setHeader('Allow', ['POST']);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

 

4. Create View (Next.js Page)
Implement a form in a Next.js page to allow users to create new blog posts. Place this in pages/blogs/new.tsx.

// pages/blogs/new.tsx
import { useState } from 'react';
import axios from 'axios';
import { useRouter } from 'next/router';

const NewBlogPage = () => {
  const [formData, setFormData] = useState({
    category_id: '',
    title: '',
    banner: '',
    slug: '',
    short_description: '',
    description: '',
    meta_title: '',
    meta_img: '',
    meta_description: '',
    meta_keywords: '',
  });

  const router = useRouter();

  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    const { name, value } = e.target;
    setFormData(prevState => ({
      ...prevState,
      [name]: value,
    }));
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      await axios.post('/api/blogs', formData);
      alert('Blog post has been created successfully');
      router.push('/blogs');
    } catch (error) {
      console.error('Error creating blog post:', error);
      alert('Failed to create blog post');
    }
  };

  return (
    <div>
      <h1>Create New Blog Post</h1>
      <form onSubmit={handleSubmit}>
        {/* Add form fields here */}
        <button type=submit>Create Blog Post</button>
      </form>
    </div>
  );
};

export default NewBlogPage;

 

Summary
Controller: The createBlogPost function in controllers/blogController.ts handles creating a new blog post.
API Route: The API route in pages/api/blogs.ts handles the POST request for creating a new blog post.
View: The form in pages/blogs/new.tsx allows users to submit new blog posts.
This setup ensures that your Next.js application can handle the creation of new blog posts while maintaining a clean MVC structure. Adjust the code as needed to fit your specific requirements.

Next.js application using TypeScript and Prisma, you need to handle form submission, validate the input, update the existing blog post, and save the changes to the database.

1. Define Prisma Schema
Ensure your Prisma schema includes a model for Blog.

// schema.prisma
model Blog {
  id                Int      @id @default(autoincrement())
  category_id       Int
  title             String
  banner            String
  slug              String
  short_description String
  description       String
  meta_title        String
  meta_img          String
  meta_description  String
  meta_keywords     String
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt

  // Add a relation to the BlogCategory model if necessary
  category          BlogCategory @relation(fields: [category_id], references: [id])
}

 

2. Create Controller Function
Implement a controller function to handle updating an existing blog post. Place this in a file like controllers/blogController.ts.

// controllers/blogController.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export async function updateBlogPost(id: number, data: any) {
  const slug = data.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');

  return prisma.blog.update({
    where: { id },
    data: {
      category: { connect: { id: data.category_id } },
      title: data.title,
      banner: data.banner,
      slug,
      short_description: data.short_description,
      description: data.description,
      meta_title: data.meta_title,
      meta_img: data.meta_img,
      meta_description: data.meta_description,
      meta_keywords: data.meta_keywords,
    },
  });
}

 

3. Set up API Route
Create an API route to handle the PUT request for updating an existing blog post. Place this in pages/api/blogs/[id].ts.

// pages/api/blogs/[id].ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { updateBlogPost } from '@/app/server/controllers/blogController';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { id } = req.query;

  if (req.method === 'PUT') {
    try {
      const blog = await updateBlogPost(Number(id), req.body);
      res.status(200).json({ blog });
    } catch (error) {
      console.error(error);
      res.status(500).json({ error: 'Internal Server Error' });
    }
  } else {
    res.setHeader('Allow', ['PUT']);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

 

4. Create View (Next.js Page)
No changes are needed in the view part. Assuming you already have a form in a Next.js page to allow users to update blog posts (pages/blogs/edit.tsx), you can keep it as is.

Summary
Controller: The updateBlogPost function in controllers/blogController.ts handles updating an existing blog post.
API Route: The API route in pages/api/blogs/[id].ts handles the PUT request for updating an existing blog post.
View: Assuming you already have a form in pages/blogs/edit.tsx, no changes are needed in the view part.
This setup ensures that your Next.js application can handle updating existing blog posts while maintaining a clean MVC structure. Adjust the code as needed to fit your specific requirements.

Next.js application using TypeScript and Prisma, you can create an API route to handle the status change of a blog post

1. Define Prisma Schema
Ensure your Prisma schema includes a model for Blog.

// schema.prisma
model Blog {
  id                Int      @id @default(autoincrement())
  // Other fields
  status            String
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt
}

 

2. Create Controller Function
Implement a controller function to handle changing the status of a blog post. Place this in a file like controllers/blogController.ts.

// controllers/blogController.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export async function changeBlogPostStatus(id: number, status: string) {
  return prisma.blog.update({
    where: { id },
    data: { status },
  });
}

 

3. Set up API Route
Create an API route to handle the POST request for changing the status of a blog post. Place this in pages/api/blogs/change-status.ts.

// pages/api/blogs/change-status.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { changeBlogPostStatus } from '@/app/server/controllers/blogController';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'POST') {
    const { id, status } = req.body;

    try {
      await changeBlogPostStatus(id, status);
      res.status(200).json({ message: 'Status changed successfully' });
    } catch (error) {
      console.error(error);
      res.status(500).json({ error: 'Internal Server Error' });
    }
  } else {
    res.setHeader('Allow', ['POST']);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

 

Summary
Controller: The changeBlogPostStatus function in controllers/blogController.ts handles changing the status of a blog post.
API Route: The API route in pages/api/blogs/change-status.ts handles the POST request for changing the status of a blog post.
This setup ensures that your Next.js application can handle changing the status of a blog post while maintaining a clean MVC structure. Adjust the code as needed to fit your specific requirements.

Next.js application using TypeScript and Prisma, you can create an API route to handle the deletion of a blog post

1. Define Prisma Schema
Ensure your Prisma schema includes a model for Blog.

// schema.prisma
model Blog {
  id                Int      @id @default(autoincrement())
  // Other fields
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt
}

 

2. Create Controller Function
Implement a controller function to handle deleting a blog post. Place this in a file like controllers/blogController.ts.

// controllers/blogController.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export async function deleteBlogPost(id: number) {
  return prisma.blog.delete({
    where: { id },
  });
}

 

3. Set up API Route
Create an API route to handle the DELETE request for deleting a blog post. Place this in pages/api/blogs/[id].ts.

// pages/api/blogs/[id].ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { deleteBlogPost } from '@/app/server/controllers/blogController';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { id } = req.query;

  if (req.method === 'DELETE') {
    try {
      await deleteBlogPost(Number(id));
      res.status(200).json({ message: 'Blog post deleted successfully' });
    } catch (error) {
      console.error(error);
      res.status(500).json({ error: 'Internal Server Error' });
    }
  } else {
    res.setHeader('Allow', ['DELETE']);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

 

Summary
Controller: The deleteBlogPost function in controllers/blogController.ts handles deleting a blog post.
API Route: The API route in pages/api/blogs/[id].ts handles the DELETE request for deleting a blog post.
This setup ensures that your Next.js application can handle deleting a blog post while maintaining a clean MVC structure. Adjust the code as needed to fit your specific requirements.

Next.js application using TypeScript and Prisma, you would need to adjust the logic to fetch and filter blog posts

1. Define Prisma Schema
Ensure your Prisma schema includes models for Blog and BlogCategory.

// schema.prisma
model Blog {
  id                Int      @id @default(autoincrement())
  category_id       Int
  title             String
  short_description String
  status            Boolean
  created_at        DateTime @default(now())
  updated_at        DateTime @updatedAt

  category          BlogCategory @relation(fields: [category_id], references: [id])
}

model BlogCategory {
  id                Int      @id @default(autoincrement())
  slug              String   @unique
  // Add other fields if necessary
  created_at        DateTime @default(now())
  updated_at        DateTime @updatedAt
}

 

2. Create Controller Function
Implement a controller function to handle fetching and filtering blog posts. Place this in a file like controllers/blogController.ts.

// controllers/blogController.ts
import { PrismaClient, Blog } from '@prisma/client';

const prisma = new PrismaClient();

export async function getAllBlogs(selectedCategories: string[], search: string | null) {
  const where = {
    status: true,
    AND: [],
  };

  if (search) {
    where.AND.push(
      {
        OR: [
          { title: { contains: search, mode: 'insensitive' } },
          { short_description: { contains: search, mode: 'insensitive' } },
        ],
      },
    );
  }

  if (selectedCategories.length > 0) {
    const blogCategories = await prisma.blogCategory.findMany({
      where: { slug: { in: selectedCategories } },
      select: { id: true },
    });

    where.AND.push({ category_id: { in: blogCategories.map(category => category.id) } });
  }

  const blogs = await prisma.blog.findMany({
    where,
    orderBy: { created_at: 'desc' },
    take: 12,
    include: { category: true },
  });

  return blogs;
}

 

3. Set up API Route
Create an API route to handle the GET request for fetching and filtering blog posts. Place this in pages/api/blogs.ts.

// pages/api/blogs.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { getAllBlogs } from '@/app/server/controllers/blogController';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { selectedCategories = [], search = null } = req.query;

  try {
    const blogs = await getAllBlogs(Array.isArray(selectedCategories) ? selectedCategories : [selectedCategories], search);
    res.status(200).json({ blogs });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
}

 

Summary
Controller: The getAllBlogs function in controllers/blogController.ts handles fetching and filtering blog posts based on selected categories and search query.
API Route: The API route in pages/api/blogs.ts handles the GET request for fetching and filtering blog posts.
This setup ensures that your Next.js application can handle fetching and filtering blog posts while maintaining a clean MVC structure. Adjust the code as needed to fit your specific requirements.

Next.js application using TypeScript and Prisma, you can create an API route to handle the retrieval of blog details based on the slug.

1. Define Prisma Schema
Ensure your Prisma schema includes a model for Blog.

// schema.prisma
model Blog {
  id                Int      @id @default(autoincrement())
  // Other fields
  slug              String   @unique
  status            Boolean
  created_at        DateTime @default(now())
  updated_at        DateTime @updatedAt
}

 

2. Create Controller Function
Implement a controller function to handle fetching blog details based on the slug. Place this in a file like controllers/blogController.ts.

// controllers/blogController.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export async function getBlogDetails(slug: string) {
  return prisma.blog.findUnique({
    where: { slug },
    include: { /* Include any related models if needed */ },
  });
}

export async function getRecentBlogs() {
  return prisma.blog.findMany({
    where: { status: true },
    orderBy: { created_at: 'desc' },
    take: 9,
  });
}

 

3. Set up API Route
Create an API route to handle the GET request for fetching blog details based on the slug. Place this in pages/api/blogs/[slug].ts.

// pages/api/blogs/[slug].ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { getBlogDetails, getRecentBlogs } from '@/app/server/controllers/blogController';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { slug } = req.query;

  try {
    const blog = await getBlogDetails(slug as string);
    const recentBlogs = await getRecentBlogs();
    
    if (blog) {
      res.status(200).json({ blog, recentBlogs });
    } else {
      res.status(404).json({ error: 'Blog not found' });
    }
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
}

 

Summary
Controller: The getBlogDetails function in controllers/blogController.ts handles fetching blog details based on the slug, and getRecentBlogs function fetches the recent blog posts.
API Route: The API route in pages/api/blogs/[slug].ts handles the GET request for fetching blog details based on the slug.
This setup ensures that your Next.js application can handle retrieving blog details based on the slug while maintaining a clean MVC structure. Adjust the code as needed to fit your specific requirements.

Share
Newsletter

Subscribe our newsletter