Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/api-v2/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { APP_GUARD } from "@nestjs/core";
import { PrismaService } from "./common/db/prisma.service";
import { AuthGuard } from "./common/guards/auth.guard";
import { ApplicationsModule } from "./sections/applications/applications.module";
import { ShowcasesModule } from "./sections/showcases/showcases.module";
import { AuthModule } from "./sections/auth/auth.module";
import { StatusModule } from "./sections/status/status.module";
import { UtilityModule } from "./sections/utility/utility.module";
Expand All @@ -13,6 +14,7 @@ import { UtilityModule } from "./sections/utility/utility.module";
UtilityModule,
AuthModule,
ApplicationsModule,
ShowcasesModule,
StatusModule,
ConfigModule.forRoot({ isGlobal: true, cache: true }),
],
Expand Down
31 changes: 31 additions & 0 deletions apps/api-v2/src/sections/showcases/dto/create.showcase.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsISO8601, IsOptional, IsString } from "class-validator";

export class CreateShowcaseDto {
@ApiProperty({
description: "The title of the showcase.",
})
@IsString()
title: string;

@ApiProperty({
description: "The city for the showcase.",
})
@IsString()
city: string;

@ApiPropertyOptional({
description:
"The timestamp when the showcase was created. Defaults to the current time.",
example: "2025-04-19T16:45:18.767Z",
})
@IsISO8601()
@IsOptional()
createdAt?: string;

@ApiProperty({
description: "The ID of the image associated with this showcase.",
})
@IsString()
imageId: string;
}
73 changes: 73 additions & 0 deletions apps/api-v2/src/sections/showcases/dto/showcase.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { ApiProperty } from "@nestjs/swagger";

export class ShowcaseDto {
@ApiProperty({
example: "00000000-0000-0000-0000-000000000000",
description: "The unique ID of the showcase.",
})
id: string;

@ApiProperty({
example: "Showcase Title",
description: "The title of the showcase.",
})
title: string;

@ApiProperty({
example: "New York",
description: "The city for the showcase.",
})
city: string;

@ApiProperty({
example: "2025-04-19T16:45:18.767Z",
description: "The timestamp when the showcase was created.",
})
createdAt: string;

@ApiProperty({
example: "00000000-0000-0000-0000-000000000000",
description: "The ID of the build team this showcase belongs to.",
})
buildTeamId: string;

@ApiProperty({
example: "00000000-0000-0000-0000-000000000000",
description: "The ID of the image associated with this showcase.",
})
imageId: string;

@ApiProperty({
example: {
name: "Build Team Name",
location: "Country",
slug: "build-team-slug",
icon: "https://example.com/icon.png",
id: "00000000-0000-0000-0000-000000000000",
},
description: "The build team object for this showcase.",
required: false,
})
buildTeam?: {
name: string;
location: string;
slug: string;
icon: string;
id: string;
};

@ApiProperty({
example: {
id: "00000000-0000-0000-0000-000000000000",
name: "image.png",
url: "https://example.com/image.png",
},
description: "The image object for this showcase.",
required: false,
})
image?: {
id: string;
name: string;
url: string;
};
}
15 changes: 15 additions & 0 deletions apps/api-v2/src/sections/showcases/dto/update.showcase.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { IsOptional, IsString } from "class-validator";

export class UpdateShowcaseDto {
@IsString()
@IsOptional()
title: string;

@IsString()
@IsOptional()
city: string;

@IsString()
@IsOptional()
imageId: string;
}
157 changes: 157 additions & 0 deletions apps/api-v2/src/sections/showcases/showcases.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Put,
Query,
Req,
} from "@nestjs/common";
import { ApiBearerAuth, ApiOperation } from "@nestjs/swagger";
import { Request } from "express";
import {
ApiDefaultResponse,
ApiErrorResponse,
ApiPaginatedResponseDto,
} from "src/common/decorators/api-response.decorator";
import { Filter, FilterParams } from "src/common/decorators/filter.decorator";
import { Filtered } from "src/common/decorators/filtered.decorator";
import { Paginated } from "src/common/decorators/paginated.decorator";
import {
Pagination,
PaginationParams,
} from "src/common/decorators/pagination.decorator";
import { Sortable } from "src/common/decorators/sortable.decorator";
import {
Sorting,
SortingParams,
} from "src/common/decorators/sorting.decorator";
import { ShowcasesService } from "./showcases.service";
import { ShowcaseDto } from "./dto/showcase.dto";
import { CreateShowcaseDto } from "./dto/create.showcase.dto";
import { UpdateShowcaseDto } from "./dto/update.showcase.dto";

@Controller()
export class ShowcasesController {
constructor(private readonly showcasesService: ShowcasesService) {}

/**
* Returns all showcases.
*/
@Get("/showcases")
@ApiBearerAuth()
@Sortable({
defaultSortBy: "createdAt",
allowedFields: ["title", "city", "createdAt", "buildTeamId"],
defaultOrder: "desc",
})
@Paginated()
@ApiOperation({
summary: "Get All Showcases",
})
@Filtered({
fields: [
{ name: "title", required: false, type: String },
{ name: "city", required: false, type: String },
{ name: "createdAt", required: false, type: String },
{ name: "buildTeamId", required: false, type: String },
],
})
@ApiPaginatedResponseDto(ShowcaseDto, { description: "Success" })
@ApiErrorResponse({ status: 401, description: "Unauthorized" })
async getAllShowcases(
@Pagination() pagination: PaginationParams,
@Sorting() sorting: SortingParams,
@Filter() filter: FilterParams,
) {
return this.showcasesService.findAll(
pagination,
sorting.sortBy,
sorting.order,
filter.filter,
);
}

/**
* Returns all showcases for a team.
*/
@Get("/teams/:id/showcases")
@ApiBearerAuth()
@ApiOperation({
summary: "Get Team Showcases",
description: "Returns all showcases for a given team.",
})
@ApiPaginatedResponseDto(ShowcaseDto, { description: "Success" })
@ApiErrorResponse({ status: 401, description: "Unauthorized" })
async getTeamShowcases(
@Param("id") id: string,
@Query("slug") slug?: string,
) {
return this.showcasesService.getTeamShowcases(id, !!slug);
}

/**
* Creates a new showcase.
*/
@Post("/showcases")
@ApiBearerAuth()
@ApiOperation({
summary: "Create Showcase",
})
@ApiDefaultResponse(ShowcaseDto, {
status: 201,
description: "Showcase created successfully.",
})
@ApiErrorResponse({ status: 401, description: "Unauthorized" })
@ApiErrorResponse({ status: 400, description: "Bad Request" })
async createShowcase(
@Body() createShowcaseDto: CreateShowcaseDto,
@Req() req: Request,
) {
return this.showcasesService.createShowcase(
createShowcaseDto,
req.token.id,
);
}

/**
* Updates a showcase.
*/
@Put("/showcases/:id")
@ApiBearerAuth()
@ApiOperation({
summary: "Update Showcase",
})
@ApiDefaultResponse(ShowcaseDto, {
status: 200,
description: "Showcase updated successfully.",
})
@ApiErrorResponse({ status: 401, description: "Unauthorized" })
@ApiErrorResponse({ status: 400, description: "Bad Request" })
async updateShowcase(
@Param("id") id: string,
@Body() updateShowcaseDto: UpdateShowcaseDto,
) {
return this.showcasesService.updateShowcase(id, updateShowcaseDto);
}

/**
* Deletes a showcase.
*/
@Delete("/showcases/:id")
@ApiBearerAuth()
@ApiOperation({
summary: "Delete Showcase",
})
@ApiDefaultResponse(ShowcaseDto, {
status: 200,
description: "Showcase deleted successfully.",
})
@ApiErrorResponse({ status: 401, description: "Unauthorized" })
@ApiErrorResponse({ status: 400, description: "Bad Request" })
async deleteShowcase(@Param("id") id: string) {
return this.showcasesService.deleteShowcase(id);
}
}
9 changes: 9 additions & 0 deletions apps/api-v2/src/sections/showcases/showcases.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from "@nestjs/common";
import { ShowcasesController } from "./showcases.controller";
import { PrismaService } from "src/common/db/prisma.service";

@Module({
controllers: [ShowcasesController],
providers: [PrismaService],
})
export class ShowcasesModule {}
Loading