Skip to content

Commit

Permalink
Merge pull request #29 from kentibs/setup/monitoring
Browse files Browse the repository at this point in the history
feat: add post event api
  • Loading branch information
Tibz-Dankan authored Jan 7, 2024
2 parents bdfba58 + c852851 commit 1fb2666
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cSpell.words": ["sendgrid", "signin", "superadmin", "uuidv"]
"cSpell.words": ["fieldname", "sendgrid", "signin", "superadmin", "uuidv"]
}
48 changes: 48 additions & 0 deletions prisma/migrations/20240107212616_test/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
-- CreateEnum
CREATE TYPE "EventCategory" AS ENUM ('exhibition', 'conference');

-- CreateTable
CREATE TABLE "_events" (
"eventId" TEXT NOT NULL,
"postByUserId" TEXT NOT NULL,
"category" "EventCategory" NOT NULL DEFAULT 'exhibition',
"title" TEXT NOT NULL,
"description" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3),

CONSTRAINT "_events_pkey" PRIMARY KEY ("eventId")
);

-- CreateTable
CREATE TABLE "_event_images" (
"eventImageId" TEXT NOT NULL,
"eventId" TEXT NOT NULL,
"imageUrl" TEXT,
"imagePath" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3),

CONSTRAINT "_event_images_pkey" PRIMARY KEY ("eventImageId")
);

-- CreateIndex
CREATE INDEX "_events_eventId_idx" ON "_events"("eventId");

-- CreateIndex
CREATE INDEX "_events_postByUserId_idx" ON "_events"("postByUserId");

-- CreateIndex
CREATE INDEX "_events_category_idx" ON "_events"("category");

-- CreateIndex
CREATE INDEX "_event_images_eventImageId_idx" ON "_event_images"("eventImageId");

-- CreateIndex
CREATE INDEX "_event_images_eventId_idx" ON "_event_images"("eventId");

-- AddForeignKey
ALTER TABLE "_events" ADD CONSTRAINT "_events_postByUserId_fkey" FOREIGN KEY ("postByUserId") REFERENCES "_users"("userId") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "_event_images" ADD CONSTRAINT "_event_images_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "_events"("eventId") ON DELETE RESTRICT ON UPDATE CASCADE;
39 changes: 38 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ model User {
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
AccessTokens AccessToken[]
SignupToken SignupToken[]
SignupTokens SignupToken[]
Events Event[]
@@index([userId])
@@index([email])
Expand Down Expand Up @@ -74,6 +75,42 @@ model AccessToken {
@@map("_access_tokens")
}

enum EventCategory {
exhibition
conference
}

model Event {
eventId String @id @default(uuid())
User User @relation(fields: [postByUserId], references: [userId])
postByUserId String
category EventCategory @default(exhibition)
title String @db.Text
description String @db.Text
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
EventImages EventImage[]
@@index([eventId])
@@index([postByUserId])
@@index([category])
@@map("_events")
}

model EventImage {
eventImageId String @id @default(uuid())
Event Event @relation(fields: [eventId], references: [eventId])
eventId String
imageUrl String? @db.Text
imagePath String? @db.Text
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
@@index([eventImageId])
@@index([eventId])
@@map("_event_images")
}

// PRISMA COMMNANDS

// INITIALIZE PRISMA
Expand Down
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { errorController } from "./controllers/errorController";
import { rateLimitController } from "./controllers/rateLimitController";
import { userRoutes } from "./routes/auth/userRoutes";
import { tokenRoutes } from "./routes/token/tokenRoutes";
import { eventRoutes } from "./routes/event/eventRoutes";
import { monitoringRoutes } from "./routes/monitoring/monitoringRoutes";
import {
startRequestMonitoringTimer,
Expand Down Expand Up @@ -34,6 +35,7 @@ app.use(startRequestMonitoringTimer);

app.use("/api/v1/users", userRoutes);
app.use("/api/v1/tokens", tokenRoutes);
app.use("/api/v1/events", eventRoutes);

app.use(monitoringRoutes);
app.use(endRequestMonitoringTimer);
Expand Down
97 changes: 97 additions & 0 deletions src/controllers/eventsController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Request, Response, NextFunction } from "express";
import { AppError } from "../utils/error";
import { asyncHandler } from "../utils/asyncHandler";
import { PrismaClient } from "@prisma/client";
import { Upload } from "../utils/upload";
import { EventCategory } from "../types/eventCategory";
import { TFile } from "../types/file";

const prisma = new PrismaClient();
const Event = prisma.event;
const EventImage = prisma.eventImage;

const validateEventCategory = (event: string): boolean => {
const isExhibition = event === EventCategory.EXHIBITION;
const isConference = event === EventCategory.CONFERENCE;

if (isExhibition || isConference) {
return true;
}
return false;
};

export const postEvent = asyncHandler(
async (req: Request, res: Response, next: NextFunction) => {
const title = req.body.title as string;
const category = req.body.category as EventCategory;
const description = req.body.description as string;
const userId = res.locals.user.userId;
const files = req.files as TFile[];

if (!userId) {
return next(new AppError("Please provide the userId", 400));
}
if (!title || !category || !description) {
return next(new AppError("Please fill out all fields", 400));
}
if (!validateEventCategory(category)) {
return next(new AppError("Please provide a valid event category", 400));
}
if (files == undefined) {
return next(new AppError("Please Provide at least one event photo", 400));
}

const newEvent = await Event.create({
data: {
title: title,
category: category,
description: description,
postByUserId: userId,
},
select: {
eventId: true,
title: true,
category: true,
description: true,
createdAt: true,
updatedAt: true,
},
});
res.locals.event = newEvent;
next();
}
);

export const uploadEventImages = asyncHandler(
async (req: Request, res: Response, next: NextFunction) => {
const files = req.files as TFile[];

const event = res.locals.event;
const eventId = event.eventId as string;

for (let i = 0; i < files.length; i++) {
const imagePath = `events/${Date.now()}_${files[i].originalname}`;
const upload = await new Upload(imagePath, next).add(files[i]);
const url = upload?.url as string;

console.log("url from firebase");
console.log(url);

await EventImage.create({
data: { eventId: eventId, imageUrl: url, imagePath: imagePath },
});
}

const eventImages = await EventImage.findMany({
where: { eventId: { equals: eventId } },
select: { imageUrl: true },
});
event.eventImages = eventImages;

res.status(201).json({
status: "success",
message: "Event created successfully",
data: { event: event },
});
}
);
19 changes: 19 additions & 0 deletions src/routes/event/eventRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import express from "express";
import { protectSuperAdmin } from "../../controllers/userController";
import { uploadFiles } from "../../utils/upload";
import {
postEvent,
uploadEventImages,
} from "../../controllers/eventsController";

const router = express.Router();

router.post(
"/post-event",
uploadFiles,
protectSuperAdmin,
postEvent,
uploadEventImages
);

export { router as eventRoutes };
4 changes: 4 additions & 0 deletions src/types/eventCategory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum EventCategory {
EXHIBITION = "exhibition",
CONFERENCE = "conference",
}
8 changes: 8 additions & 0 deletions src/types/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type TFile = {
fieldname: string;
originalname: string;
encoding: string;
mimetype: string;
buffer: Buffer;
size: number;
};

0 comments on commit 1fb2666

Please sign in to comment.