Skip to content

Commit

Permalink
Merge pull request hngprojects#491 from Nainah23/feat/Create-Squeeze-…
Browse files Browse the repository at this point in the history
…Page

feat: Create Squeeze Page
  • Loading branch information
PreciousIfeaka authored Aug 8, 2024
2 parents 44e3a47 + 630b344 commit 74478b4
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 1 deletion.
88 changes: 88 additions & 0 deletions src/controllers/SqueezeController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Request, Response } from "express";
import { SqueezeService } from "../services";

class SqueezeController {
private squeezeService: SqueezeService;

constructor() {
this.squeezeService = new SqueezeService();
}

/**
* @openapi
* /api/v1/squeeze-pages:
* post:
* tags:
* - Squeeze
* summary: Create a new squeeze
* description: Create a new squeeze entry.
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* email:
* type: string
* first_name:
* type: string
* last_name:
* type: string
* phone:
* type: string
* location:
* type: string
* job_title:
* type: string
* company:
* type: string
* interests:
* type: array
* referral_source:
* type: string
* required:
* - email
* - first_name
* - last_name
* responses:
* 201:
* description: Squeeze created successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: "success"
* message:
* type: string
* example: "Squeeze created successfully"
* data:
* type: object
* 400:
* description: Bad request
* 409:
* description: Conflict
*/
public createSqueeze = async (req: Request, res: Response) => {
try {
const squeezeData = req.body;
const squeeze = await this.squeezeService.createSqueeze(squeezeData); // Use the instance method
res.status(201).json({
status: "success",
message: "Squeeze record created successfully.",
data: squeeze,
});
} catch (error) {
res.status(500).json({
status: "error",
message: "An error occurred while creating the squeeze record.",
error: error.message,
});
}
};
}

export { SqueezeController };
1 change: 1 addition & 0 deletions src/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export * from "./contactController";
export * from "./FaqController";
export * from "./OrgController";
export * from "./runTestController";
export * from "./SqueezeController";
2 changes: 1 addition & 1 deletion src/middleware/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from "./error";
export * from "./auth";
export * from "./checkUserRole";
export * from "./organizationValidation";
export * from "./organizationValidation";
1 change: 1 addition & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export * from "./invitation";
export * from "./contact";
export * from "./faq";
export * from "./orgInviteToken";
export * from "./squeeze";
48 changes: 48 additions & 0 deletions src/models/squeeze.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from "typeorm";

@Entity()
class Squeeze {
@PrimaryGeneratedColumn("uuid")
id: string;

@Column({ unique: true })
email: string;

@Column({ nullable: true })
first_name?: string;

@Column({ nullable: true })
last_name?: string;

@Column({ nullable: true })
phone?: string;

@Column({ nullable: true })
location?: string;

@Column({ nullable: true })
job_title?: string;

@Column({ nullable: true })
company?: string;

@Column("simple-array", { nullable: true })
interests?: string[];

@Column({ nullable: true })
referral_source?: string;

@CreateDateColumn()
createdAt: Date;

@UpdateDateColumn()
updatedAt: Date;
}

export { Squeeze };
2 changes: 2 additions & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ export * from "./testimonial";
export * from "./user";
export * from "./faq";
export * from "./run-test";
export * from "./squeeze";
export * from "./newsLetterSubscription";

14 changes: 14 additions & 0 deletions src/routes/squeeze.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Router } from "express";
import { SqueezeController } from "../controllers";
import { authMiddleware } from "../middleware";

const squeezeRoute = Router();
const squeezecontroller = new SqueezeController();

squeezeRoute.post(
"/squeeze-pages",
authMiddleware,
squeezecontroller.createSqueeze.bind(squeezecontroller),
);

export { squeezeRoute };
68 changes: 68 additions & 0 deletions src/schema/squeezeSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { z } from "zod";

/**
* @openapi
* components:
* schemas:
* Squeeze:
* type: object
* properties:
* id:
* type: string
* format: uuid
* example: "e02c7c4e-bb92-4f9a-8d91-bc9e63c5b8d5"
* email:
* type: string
* format: email
* example: "[email protected]"
* first_name:
* type: string
* example: "Nainah"
* last_name:
* type: string
* example: "Kamah"
* phone:
* type: string
* example: "+254123456789"
* location:
* type: string
* example: "Nairobi"
* job_title:
* type: string
* example: "Backend Engineer"
* company:
* type: string
* example: "HNG"
* interests:
* type: array
* example: ["Tech", "Politics", "Youth"]
* referral_source:
* type: string
* example: "Internet"
* createdAt:
* type: string
* format: date-time
* example: "2024-08-03T14:00:00Z"
* updatedAt:
* type: string
* format: date-time
* example: "2024-08-03T14:00:00Z"
* required:
* - id
* - email
* - createdAt
* - updatedAt
*/
const squeezeSchema = z.object({
email: z.string().email("Invalid email address"),
first_name: z.string().min(1, "First name is required"),
last_name: z.string().min(1, "Last name is required"),
phone: z.string().optional(),
location: z.string().optional(),
job_title: z.string().optional(),
company: z.string().optional(),
interests: z.array(z.string()).optional(),
referral_source: z.string().optional(),
});

export { squeezeSchema };
1 change: 1 addition & 0 deletions src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from "./payment/flutter.service";
export * from "./contactService";
export * from "./faq.services";
export * from "./org.services";
export * from "./squeezeService";
41 changes: 41 additions & 0 deletions src/services/squeezeService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Squeeze } from "../models";
import AppDataSource from "../data-source";
import { Conflict, BadRequest } from "../middleware";
import { squeezeSchema } from "../schema/squeezeSchema";
import { Repository } from "typeorm";

class SqueezeService {
private squeezeRepository: Repository<Squeeze>;

constructor() {
this.squeezeRepository = AppDataSource.getRepository(Squeeze);
}

public async createSqueeze(data: Partial<Squeeze>): Promise<Squeeze> {
const validation = squeezeSchema.safeParse(data);
if (!validation.success) {
throw new Conflict(
"Validation failed: " +
validation.error.errors.map((e) => e.message).join(", ")
);
}

try {
const existingSqueeze = await this.squeezeRepository.findOne({
where: { email: data.email },
});

if (existingSqueeze) {
throw new Conflict("A squeeze has already been generated using this email");
}

const squeeze = this.squeezeRepository.create(data);
const savedSqueeze = await this.squeezeRepository.save(squeeze);
return savedSqueeze;
} catch (error) {
throw new BadRequest("Failed to create squeeze: " + error.message);
}
}
}

export { SqueezeService };

0 comments on commit 74478b4

Please sign in to comment.