Skip to content

Commit 9a5142e

Browse files
committed
finish onboarding
1 parent 83b1a51 commit 9a5142e

File tree

8 files changed

+221
-6
lines changed

8 files changed

+221
-6
lines changed

backend/typescript/graphql/index.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { makeExecutableSchema, gql } from "apollo-server-express";
1+
import { gql, makeExecutableSchema } from "apollo-server-express";
22
import { applyMiddleware } from "graphql-middleware";
33
import { merge } from "lodash";
44

@@ -8,16 +8,18 @@ import {
88
isAuthorizedByUserId,
99
} from "../middlewares/auth";
1010
import authResolvers from "./resolvers/authResolvers";
11-
import authType from "./types/authType";
11+
import dashboardResolvers from "./resolvers/dashboardResolvers";
1212
import entityResolvers from "./resolvers/entityResolvers";
13-
import entityType from "./types/entityType";
1413
import simpleEntityResolvers from "./resolvers/simpleEntityResolvers";
15-
import simpleEntityType from "./types/simpleEntityType";
14+
import teamMemberResolvers from "./resolvers/teamMemberResolvers";
1615
import userResolvers from "./resolvers/userResolvers";
17-
import userType from "./types/userType";
16+
import authType from "./types/authType";
1817
import dashboardType from "./types/dashboardType";
19-
import dashboardResolvers from "./resolvers/dashboardResolvers";
18+
import entityType from "./types/entityType";
2019
import reviewType from "./types/reviewType";
20+
import simpleEntityType from "./types/simpleEntityType";
21+
import teamMemberType from "./types/teamMemberType";
22+
import userType from "./types/userType";
2123

2224
const query = gql`
2325
type Query {
@@ -41,13 +43,15 @@ const executableSchema = makeExecutableSchema({
4143
simpleEntityType,
4244
userType,
4345
dashboardType,
46+
teamMemberType,
4447
],
4548
resolvers: merge(
4649
authResolvers,
4750
entityResolvers,
4851
simpleEntityResolvers,
4952
userResolvers,
5053
dashboardResolvers,
54+
teamMemberResolvers,
5155
),
5256
});
5357

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import TeamMemberService from "../../services/implementations/teamMemberService";
2+
import { CreateTeamMemberDTO, TeamMemberDTO } from "../../types";
3+
import { getErrorMessage } from "../../utilities/errorUtils";
4+
5+
const teamMemberService = new TeamMemberService();
6+
7+
const teamMemberResolvers = {
8+
Query: {
9+
teamMembers: async (): Promise<TeamMemberDTO[]> => {
10+
try {
11+
return await teamMemberService.getTeamMembers();
12+
} catch (error) {
13+
throw new Error(getErrorMessage(error));
14+
}
15+
},
16+
},
17+
Mutation: {
18+
createTeamMember: async (
19+
_: unknown,
20+
{ input }: { input: CreateTeamMemberDTO },
21+
): Promise<TeamMemberDTO> => {
22+
try {
23+
return await teamMemberService.createTeamMember(input);
24+
} catch (error) {
25+
throw new Error(getErrorMessage(error));
26+
}
27+
},
28+
},
29+
};
30+
31+
export default teamMemberResolvers;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { gql } from "apollo-server-express";
2+
3+
const teamMemberType = gql`
4+
enum TeamRole {
5+
PM
6+
DESIGNER
7+
PL
8+
DEVELOPER
9+
}
10+
11+
type TeamMemberDTO {
12+
id: ID!
13+
firstName: String!
14+
lastName: String!
15+
teamRole: TeamRole!
16+
}
17+
18+
input CreateTeamMemberDTO {
19+
firstName: String!
20+
lastName: String!
21+
teamRole: TeamRole!
22+
}
23+
24+
extend type Query {
25+
teamMembers: [TeamMemberDTO!]!
26+
}
27+
28+
extend type Mutation {
29+
createTeamMember(input: CreateTeamMemberDTO!): TeamMemberDTO!
30+
}
31+
`;
32+
33+
export default teamMemberType;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { DataTypes } from "sequelize";
2+
import { Migration } from "../umzug";
3+
4+
const TABLE_NAME = "team_members";
5+
6+
export const up: Migration = async ({ context: sequelize }) => {
7+
await sequelize.getQueryInterface().createTable(TABLE_NAME, {
8+
id: {
9+
type: DataTypes.UUID,
10+
defaultValue: DataTypes.UUIDV4,
11+
allowNull: false,
12+
primaryKey: true,
13+
},
14+
firstName: {
15+
type: DataTypes.STRING,
16+
allowNull: false,
17+
},
18+
lastName: {
19+
type: DataTypes.STRING,
20+
allowNull: false,
21+
},
22+
teamRole: {
23+
type: DataTypes.ENUM("PM", "DESIGNER", "PL", "DEVELOPER"),
24+
allowNull: false,
25+
},
26+
createdAt: {
27+
type: DataTypes.DATE,
28+
allowNull: false,
29+
defaultValue: DataTypes.NOW,
30+
},
31+
updatedAt: {
32+
type: DataTypes.DATE,
33+
allowNull: false,
34+
defaultValue: DataTypes.NOW,
35+
},
36+
});
37+
};
38+
39+
export const down: Migration = async ({ context: sequelize }) => {
40+
await sequelize.getQueryInterface().dropTable(TABLE_NAME);
41+
await sequelize
42+
.getQueryInterface()
43+
.sequelize.query('DROP TYPE IF EXISTS "enum_team_members_teamRole";');
44+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* eslint import/no-cycle: 0 */
2+
import { Column, DataType, Model, Table } from "sequelize-typescript";
3+
import { TeamRole, teamRoleValues } from "../types";
4+
5+
@Table({ tableName: "team_members" })
6+
export default class TeamMember extends Model {
7+
@Column({
8+
type: DataType.UUID,
9+
defaultValue: DataType.UUIDV4,
10+
primaryKey: true,
11+
})
12+
id!: string;
13+
14+
@Column({ type: DataType.STRING, allowNull: false })
15+
firstName!: string;
16+
17+
@Column({ type: DataType.STRING, allowNull: false })
18+
lastName!: string;
19+
20+
@Column({
21+
type: DataType.ENUM(...teamRoleValues),
22+
allowNull: false,
23+
})
24+
teamRole!: TeamRole;
25+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import TeamMember from "../../models/teamMember.model"; // <- Sequelize model
2+
import { CreateTeamMemberDTO, TeamMemberDTO } from "../../types";
3+
import { getErrorMessage } from "../../utilities/errorUtils";
4+
import logger from "../../utilities/logger";
5+
import ITeamMemberService from "../interfaces/teamMemberService";
6+
7+
const Logger = logger(__filename);
8+
9+
function toDTO(model: TeamMember): TeamMemberDTO {
10+
return {
11+
id: model.id,
12+
firstName: model.firstName,
13+
lastName: model.lastName,
14+
teamRole: model.teamRole,
15+
};
16+
}
17+
18+
class TeamMemberService implements ITeamMemberService {
19+
getTeamMembers = async (): Promise<TeamMemberDTO[]> => {
20+
try {
21+
const teamMembers = await TeamMember.findAll();
22+
return teamMembers.map(toDTO);
23+
} catch (error: unknown) {
24+
Logger.error(
25+
`Failed to get team members. Reason = ${getErrorMessage(error)}`,
26+
);
27+
throw error;
28+
}
29+
};
30+
31+
createTeamMember = async (
32+
teamMember: CreateTeamMemberDTO,
33+
): Promise<TeamMemberDTO> => {
34+
try {
35+
const newTeamMember = await TeamMember.create(teamMember);
36+
return toDTO(newTeamMember);
37+
} catch (error: unknown) {
38+
Logger.error(
39+
`Failed to create team member. Reason = ${getErrorMessage(error)}`,
40+
);
41+
throw error;
42+
}
43+
};
44+
}
45+
46+
export default TeamMemberService;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { CreateTeamMemberDTO, TeamMemberDTO } from "../../types";
2+
3+
interface ITeamMemberService {
4+
/**
5+
* Get all team member information
6+
* @returns array of TeamMemberDTO
7+
* @throws Error if team member retrieval fails
8+
*/
9+
getTeamMembers(): Promise<TeamMemberDTO[]>;
10+
11+
/**
12+
* Create a team member
13+
* @param teamMember the team member to be created
14+
* @returns a TeamMemberDTO with the created team member's information
15+
* @throws Error if team member creation fails
16+
*/
17+
createTeamMember(teamMember: CreateTeamMemberDTO): Promise<TeamMemberDTO>;
18+
}
19+
20+
export default ITeamMemberService;

backend/typescript/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
export type Role = "User" | "Admin";
22

3+
export const teamRoleValues = ["PM", "Designer", "PL", "Developer"] as const;
4+
export type TeamRole = (typeof teamRoleValues)[number];
5+
36
export enum StatusType {
47
ACCEPTED = "accepted",
58
APPLIED = "applied",
@@ -236,3 +239,12 @@ export type ReviewedApplicantRecordDTO = {
236239
review: Review;
237240
status: ReviewStatus;
238241
};
242+
243+
export type TeamMemberDTO = {
244+
id: string;
245+
firstName: string;
246+
lastName: string;
247+
teamRole: TeamRole;
248+
};
249+
250+
export type CreateTeamMemberDTO = Omit<TeamMemberDTO, "id">;

0 commit comments

Comments
 (0)