forked from hngprojects/hng_boilerplate_expressjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request hngprojects#491 from Nainah23/feat/Create-Squeeze-…
…Page feat: Create Squeeze Page
- Loading branch information
Showing
10 changed files
with
265 additions
and
1 deletion.
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,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: | ||
* - 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 }; |
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
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,4 +1,4 @@ | ||
export * from "./error"; | ||
export * from "./auth"; | ||
export * from "./checkUserRole"; | ||
export * from "./organizationValidation"; | ||
export * from "./organizationValidation"; |
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
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,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 }; |
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
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,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 }; |
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,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 | ||
* - 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 }; |
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
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,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 }; |