fixed routing to ticket screen and added markdown editor
This commit is contained in:
parent
4fa957c1a0
commit
7fdcf75739
27
Websites/jefes-nextjs/app/api/issues/route.ts
Normal file
27
Websites/jefes-nextjs/app/api/issues/route.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import { z } from 'zod';
|
||||||
|
import prisma from "@/prisma/client";
|
||||||
|
|
||||||
|
// validate the request with zod
|
||||||
|
const createIssueSchema = z.object({
|
||||||
|
title: z.string().min(1).max(255), // confirms string is between 1-255 characters
|
||||||
|
description: z.string().min(1), // confirms string has min length of 1
|
||||||
|
});
|
||||||
|
|
||||||
|
// send request
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
// return request with a promise
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
// validate the data
|
||||||
|
const validation = createIssueSchema.safeParse(body);
|
||||||
|
if (!validation.success)
|
||||||
|
return NextResponse.json(validation.error.errors, {status: 400}) // Send error 400 if data is invalid
|
||||||
|
|
||||||
|
const newIssue = await prisma.issue.create({
|
||||||
|
data: { title: body.title, description: body.description }
|
||||||
|
});
|
||||||
|
|
||||||
|
// return the issue to the client
|
||||||
|
return NextResponse.json(newIssue, {status: 201}); // status 201 means an object was created
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ import Image from "next/image";
|
|||||||
import Jefes from "../../../public/jefes_logo.jpg";
|
import Jefes from "../../../public/jefes_logo.jpg";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import issues from "@/app/issues";
|
||||||
|
|
||||||
const NavBar = () => {
|
const NavBar = () => {
|
||||||
const currentPath = usePathname();
|
const currentPath = usePathname();
|
||||||
@ -12,8 +13,10 @@ const NavBar = () => {
|
|||||||
|
|
||||||
// Create an array to hold the list items
|
// Create an array to hold the list items
|
||||||
const links = [
|
const links = [
|
||||||
{ label: "Dashboard", href: "/Dashboard" },
|
{ label: "Dashboard", href: "/dashboard" },
|
||||||
{ label: "Issues", href: "/Issues" },
|
{ label: "Issues", href: "/issues" },
|
||||||
|
{ label: "Keira", href: "/issues" },
|
||||||
|
{ label: "Jacob", href: "/issues" },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -28,9 +31,9 @@ const NavBar = () => {
|
|||||||
// className={`${link.href === currentPath ? 'text-zinc-900' : 'text-zinc-500 hover:text-zinc-800'}`}
|
// className={`${link.href === currentPath ? 'text-zinc-900' : 'text-zinc-500 hover:text-zinc-800'}`}
|
||||||
// replace with classnames object instead
|
// replace with classnames object instead
|
||||||
className={classnames({
|
className={classnames({
|
||||||
'text-zinc-900': link.href === currentPath,
|
'text-emerald-400': link.href === currentPath,
|
||||||
'text-zinc-500' : link.href !== currentPath,
|
'text-white' : link.href !== currentPath,
|
||||||
'hover:text-zinc-800': true,
|
'hover:text-zinc-500': true,
|
||||||
})}
|
})}
|
||||||
href={link.href}>
|
href={link.href}>
|
||||||
{link.label}
|
{link.label}
|
||||||
|
|||||||
@ -13,6 +13,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
color: black;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
Websites/jefes-nextjs/app/issues/new/page.tsx
Normal file
58
Websites/jefes-nextjs/app/issues/new/page.tsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
"use client";
|
||||||
|
import React from "react";
|
||||||
|
import SimpleMDE from "react-simplemde-editor";
|
||||||
|
import "easymde/dist/easymde.min.css";
|
||||||
|
import { useForm, Controller } from "react-hook-form";
|
||||||
|
import { FormEvent } from "react";
|
||||||
|
|
||||||
|
interface IssueForm {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NewIssuePage = () => {
|
||||||
|
const { register, control, handleSubmit } = useForm<IssueForm>();
|
||||||
|
// console.log(register('title'))
|
||||||
|
|
||||||
|
// handle form submit
|
||||||
|
async function onSubmit(event: FormEvent<HTMLFormElement>) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const formData = new FormData(event.currentTarget);
|
||||||
|
const response = await fetch("/api/issues", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle response if necessary
|
||||||
|
// const data = await response.json();
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form
|
||||||
|
className="max-w-xl"
|
||||||
|
// onSubmit={handleSubmit((data) => console.log(data))}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Type Here"
|
||||||
|
className="input w-full border-zinc-300 mb-2"
|
||||||
|
{...register("title")}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="desciption"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<SimpleMDE placeholder="Description" {...field}></SimpleMDE>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<button className="btn bg-emerald-400 text-black hover:bg-white">
|
||||||
|
Submit Ticket
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NewIssuePage;
|
||||||
22
Websites/jefes-nextjs/app/issues/page.tsx
Normal file
22
Websites/jefes-nextjs/app/issues/page.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import Link from 'next/link'
|
||||||
|
import React from 'react'
|
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
|
||||||
|
const IssuesPage = () => {
|
||||||
|
async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse,
|
||||||
|
) {
|
||||||
|
const data = req.body
|
||||||
|
console.log(...data)
|
||||||
|
res.redirect(307, '/issues')
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button className='btn bg-emerald-400 text-black hover:bg-white'><Link href='/issues/new'>New Ticket</Link></button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IssuesPage
|
||||||
@ -16,7 +16,7 @@ export default function RootLayout({
|
|||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" data-theme="winter">
|
<html lang="en" data-theme="night">
|
||||||
<body className={inter.className}>
|
<body className={inter.className}>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<main>{children}</main>
|
<main>{children}</main>
|
||||||
|
|||||||
Binary file not shown.
@ -11,11 +11,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "5.4.2",
|
"@prisma/client": "5.4.2",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
|
"easymde": "^2.18.0",
|
||||||
"next": "13.5.6",
|
"next": "13.5.6",
|
||||||
"prisma": "^5.4.2",
|
"prisma": "^5.4.2",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-icons": "^4.11.0"
|
"react-hook-form": "^7.47.0",
|
||||||
|
"react-icons": "^4.11.0",
|
||||||
|
"react-simplemde-editor": "^5.2.0",
|
||||||
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
|
|||||||
19
Websites/jefes-nextjs/prisma/client.ts
Normal file
19
Websites/jefes-nextjs/prisma/client.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
|
||||||
|
// ensures there is only one instance of prisma at any given moment
|
||||||
|
|
||||||
|
const prismaClientSingleton = () => {
|
||||||
|
return new PrismaClient()
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrismaClientSingleton = ReturnType<typeof prismaClientSingleton>
|
||||||
|
|
||||||
|
const globalForPrisma = globalThis as unknown as {
|
||||||
|
prisma: PrismaClientSingleton | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const prisma = globalForPrisma.prisma ?? prismaClientSingleton()
|
||||||
|
|
||||||
|
export default prisma
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
||||||
@ -17,7 +17,7 @@ const config: Config = {
|
|||||||
},
|
},
|
||||||
plugins: [require("daisyui")],
|
plugins: [require("daisyui")],
|
||||||
daisyui:{
|
daisyui:{
|
||||||
themes:["winter"],
|
themes:["night"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
export default config
|
export default config
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user