-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feature:create discustions :sprakles: * feature: vote and update status discustion :sprakles: * feature: comments ✨ * feature: bookmark :sprakles: * feat:filter and sort discustion ✨ * bug:fix bug filter use 🐛
- Loading branch information
1 parent
59af1be
commit a4ad2cd
Showing
6 changed files
with
168 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.lock | ||
*-lock.json | ||
/node_modules | ||
/.next/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
FROM node:20 | ||
|
||
# Create app directory | ||
WORKDIR /app | ||
|
||
# Install app dependencies | ||
COPY . . | ||
|
||
|
||
RUN yarn install | ||
|
||
# build | ||
RUN yarn build | ||
|
||
# Bundle app source | ||
COPY . . | ||
|
||
EXPOSE 3000 | ||
CMD [ "yarn", "start" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,121 @@ | ||
import { upload } from "@/utils/azure/storageBlob"; | ||
import getResponse from "@/utils/getResponse"; | ||
import getSessionUser from "@/utils/session"; | ||
import { PrismaClient } from "@prisma/client"; | ||
|
||
const prisma = new PrismaClient(); | ||
export async function POST(req: Request, { params }: any) { | ||
const { id } = params; | ||
const { vote } = await req.json(); | ||
if (!vote) return getResponse(null, "vote is required", 400); | ||
if (["UPVOTE", "DOWNVOTE"].includes(vote) === false) { | ||
return getResponse(400, "Invalid vote"); | ||
export async function POST(req: Request) { | ||
const data = await req.formData(); | ||
const content = data.get("content") as string; | ||
const type = data.get("type") as any; | ||
const tags = data.get("tags") as string; | ||
const attachments = data.getAll("attachments") as unknown as File[]; | ||
if (!content) { | ||
return getResponse(400, "Content is required"); | ||
} | ||
const discustion = await prisma.discustions.findFirst({ | ||
where: { | ||
id: +id, | ||
if (["DRAFT", "PUBLISHED", "ARCHIVED"].includes(type) === false) { | ||
return getResponse(400, "Invalid type"); | ||
} | ||
|
||
const user = await getSessionUser(); | ||
let attachmentsPaths: string[] = []; | ||
if (attachments) { | ||
if (!Array.isArray(attachments)) { | ||
return getResponse(400, "Attachments should be an array"); | ||
} | ||
if (attachments.length > 5) { | ||
return getResponse(400, "Maximum 5 attachments allowed"); | ||
} | ||
const attacmentUploaded = await Promise.all( | ||
attachments.map(async (attachment: any) => { | ||
const bytes = await attachment.arrayBuffer(); | ||
const buffer = Buffer.from(bytes); | ||
const now = new Date(); | ||
const prefixFile = `${now.toLocaleString()}`; | ||
return upload( | ||
"attachments", | ||
`${prefixFile} -${attachment.name}`, | ||
buffer | ||
); | ||
}) | ||
); | ||
attachmentsPaths = attacmentUploaded.map( | ||
(attachment: any) => attachment.request.url | ||
); | ||
} | ||
const discustion = await prisma.discustions.create({ | ||
data: { | ||
content, | ||
type, | ||
tags: tags ? JSON.parse(tags) : [], | ||
attachments: attachmentsPaths || [], | ||
user: { | ||
connect: { | ||
id: user?.id, | ||
}, | ||
}, | ||
}, | ||
}); | ||
return getResponse(discustion, "Discustion created", 200); | ||
} | ||
|
||
export async function GET(req: Request) { | ||
const {searchParams} = new URL(req.url); | ||
const filter_by = searchParams.get('filter_by') as "tags" | "id" | "user" | "text"; | ||
const filter_value = searchParams.get('filter_value'); | ||
const sort_by = searchParams.get("sort_by") as | ||
| "newest" | ||
| "oldest" | ||
| "top_vote"; | ||
|
||
let discustions = await prisma.discustions.findMany({ | ||
include: { | ||
user: { | ||
select: { | ||
id: true, | ||
name: true, | ||
username: true, | ||
class: { | ||
select: { | ||
id: true, | ||
name: true, | ||
}, | ||
}, | ||
// email: true, | ||
// image: true, | ||
}, | ||
}, | ||
votes: true, | ||
comments: true, | ||
}, | ||
orderBy: { | ||
created_at: "desc", | ||
}, | ||
}); | ||
if (!discustion) return getResponse(null, "Discustion not found", 404); | ||
const user = await getSessionUser(); | ||
const voteExist = | ||
discustion.votes && | ||
discustion.votes.find( | ||
(v: any) => v.user_id === user?.id && v.discustion_id === +id | ||
); | ||
if (voteExist && voteExist.type === vote) { | ||
await prisma.vote.delete({ | ||
where: { | ||
id: voteExist.id, | ||
}, | ||
}); | ||
return getResponse(discustion, "Discustion vote removed", 200); | ||
if (filter_by && filter_value) { | ||
let discustionsFiltered: any = []; | ||
if (filter_by === "tags") { | ||
discustionsFiltered = discustions.filter((discustion: any) => discustion.tags.includes(filter_value)); | ||
} else if (filter_by === "id") { | ||
discustionsFiltered = discustions.filter((discustion: any) => discustion.id === +filter_value); | ||
} else if (filter_by === "user") { | ||
discustionsFiltered = discustions.filter((discustion: any) => discustion.user.id === +filter_value); | ||
} else if (filter_by === "text") { | ||
discustionsFiltered = discustions.filter((discustion: any) => discustion.content.includes(filter_value)); | ||
} | ||
discustions = discustionsFiltered; | ||
} | ||
|
||
if (voteExist) { | ||
await prisma.vote.delete({ | ||
where: { | ||
id: voteExist.id, | ||
}, | ||
if (sort_by === "newest") { | ||
discustions = discustions.sort((a: any, b: any) => a.created_at - b.created_at); | ||
} | ||
if (sort_by === "oldest") { | ||
discustions = discustions.sort((a: any, b: any) => b.created_at - a.created_at); | ||
} | ||
if (sort_by === "top_vote") { | ||
const discustionsVote = discustions.map((item) => { | ||
return {...item, upvote: item.votes.filter((vote: any) => vote.type === "UPVOTE").length, downvote: item.votes.filter((vote: any) => vote.type === "DOWNVOTE").length}; | ||
}); | ||
discustions = discustionsVote.sort((a: any, b: any) => (b.upvote - b.downvote) - (a.upvote - a.downvote)); | ||
} | ||
await prisma.vote.create({ | ||
data: { | ||
user_id: user?.id || 1, | ||
discustion_id: +id, | ||
type: vote, | ||
}, | ||
}); | ||
|
||
return getResponse(discustion, "Discustion voted", 200); | ||
return getResponse(discustions, "Discustions fetched", 200); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,40 @@ | ||
import { upload } from "@/utils/azure/storageBlob"; | ||
import getResponse from "@/utils/getResponse"; | ||
import getSessionUser from "@/utils/session"; | ||
import { PrismaClient } from "@prisma/client"; | ||
|
||
const prisma = new PrismaClient(); | ||
export async function POST(req: Request) { | ||
const data = await req.formData(); | ||
const content = data.get("content") as string; | ||
const type = data.get("type") as any; | ||
const tags = data.get("tags") as string; | ||
const attachments = data.getAll("attachments") as unknown as File[]; | ||
if (!content) { | ||
return getResponse(400, "Content is required"); | ||
export async function POST(req: Request, { params }: any) { | ||
const { id } = params; | ||
const { vote } = await req.json(); | ||
if (!vote) return getResponse(null, "vote is required", 400); | ||
if (["UPVOTE", "DOWNVOTE"].includes(vote) === false) { | ||
return getResponse(400, "Invalid vote"); | ||
} | ||
if (["DRAFT", "PUBLISHED", "ARCHIVED"].includes(type) === false) { | ||
return getResponse(400, "Invalid type"); | ||
} | ||
|
||
const user = await getSessionUser(); | ||
let attachmentsPaths: string[] = []; | ||
if (attachments) { | ||
if (!Array.isArray(attachments)) { | ||
return getResponse(400, "Attachments should be an array"); | ||
} | ||
if (attachments.length > 5) { | ||
return getResponse(400, "Maximum 5 attachments allowed"); | ||
} | ||
const attacmentUploaded = await Promise.all( | ||
attachments.map(async (attachment: any) => { | ||
const bytes = await attachment.arrayBuffer(); | ||
const buffer = Buffer.from(bytes); | ||
const now = new Date(); | ||
const prefixFile = `${now.toLocaleString()}`; | ||
return upload( | ||
"attachments", | ||
`${prefixFile} -${attachment.name}`, | ||
buffer | ||
); | ||
}) | ||
); | ||
attachmentsPaths = attacmentUploaded.map( | ||
(attachment: any) => attachment.request.url | ||
); | ||
} | ||
const discustion = await prisma.discustions.create({ | ||
data: { | ||
content, | ||
type, | ||
tags: tags ? JSON.parse(tags) : [], | ||
attachments: attachmentsPaths || [], | ||
user: { | ||
connect: { | ||
id: user?.id, | ||
}, | ||
}, | ||
const discustion = await prisma.discustions.findFirst({ | ||
where: { | ||
id: +id, | ||
}, | ||
}); | ||
return getResponse(discustion, "Discustion created", 200); | ||
} | ||
|
||
export async function GET(req: Request) { | ||
const discustions = await prisma.discustions.findMany({ | ||
include: { | ||
user: { | ||
select: { | ||
id: true, | ||
name: true, | ||
username: true, | ||
class: { | ||
select: { | ||
id: true, | ||
name: true, | ||
}, | ||
}, | ||
// email: true, | ||
// image: true, | ||
}, | ||
}, | ||
votes: true, | ||
comments: true, | ||
}, | ||
orderBy: { | ||
created_at: "desc", | ||
}); | ||
if (!discustion) return getResponse(null, "Discustion not found", 404); | ||
const user = await getSessionUser(); | ||
const voteExist = discustion.votes && discustion.votes.find((v: any) => v.user_id === user?.id && v.type === vote); | ||
if (voteExist) { | ||
await prisma.vote.delete({ | ||
where: { | ||
id: voteExist.id, | ||
}, | ||
}); | ||
} | ||
await prisma.vote.create({ | ||
data: { | ||
user_id: user?.id ||1, | ||
discustion_id: +id, | ||
type: vote, | ||
}, | ||
}); | ||
return getResponse(discustions, "Discustions fetched", 200); | ||
|
||
return getResponse(discustion, "Discustion voted", 200); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import getResponse from '@/utils/getResponse'; | ||
import { PrismaClient } from '@prisma/client'; | ||
|
||
const prisma = new PrismaClient() | ||
export async function POST(req: Request) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters