Skip to content

Commit

Permalink
add jobtypes
Browse files Browse the repository at this point in the history
  • Loading branch information
smltr committed Aug 21, 2024
1 parent 1c4cf4b commit c83205d
Show file tree
Hide file tree
Showing 21 changed files with 634 additions and 137 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ My goal was to check all of the boxes given for the test while keeping scope tig

As mentioned I tried to keep things simple and features to a minimum so I could deliver sometihng polished, so there are definitely things I left out. If I had more time or this was a real project, I would definitely:

- Add testing
- Add features such as search, job description, and user accounts to keep track of applications/applicants
- Add QOL features such as ability to click on a job to highlight it in some way so user can read through list and keep track of what they want to apply to without having to 'save' job somewhere
- Refine UI, for example making the post new job more compact, test responsiveness more
- Add more of my own twist on the idea of a job site in general. For example, I like the idea of requiring a one sentence description of the job to be written by the poster, as well as a three adjective description of the ideal candidate (Curious, Experienced, Hardworking). Maybe require the same of candidates for their profile and don't allow for cover letters. I've also played around with the idea of 'dollar jobs' in that every posting/application requires a dollar to be paid. This would limit a lot of spam on both sides and give confidence to the process without requiring things like cover letters.
- Refine UI, for example making the post new job more compact

Binary file added apps/api/data.db
Binary file not shown.
112 changes: 66 additions & 46 deletions apps/api/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,35 @@ import { NestFactory } from '@nestjs/core';
import { AppModule } from './src/app.module';
import { PostingsService } from './src/postings/postings.service';
import { Posting } from './src/postings/posting.entity';
import { JobTypesService } from './src/jobtypes/jobtypes.service';
import { JobType } from './src/jobtypes/jobtype.entity';

async function seed() {
const app = await NestFactory.createApplicationContext(AppModule);
const postingsService = app.get(PostingsService);
const jobTypesService = app.get(JobTypesService);

// Clear existing postings and job types
await postingsService.deleteAll();
console.log('All postings have been erased!');
await jobTypesService.removeAll(); // Assuming there's a similar removeAll method in JobTypesService
console.log('All postings and job types have been erased!');

// Define job types
const jobTypeNames = ['Full Stack', 'Front End', 'Back End', 'Dev Ops', 'Data', 'AI'];

// Create job types
const jobTypes: JobType[] = [];
for (const name of jobTypeNames) {
const jobType = await jobTypesService.create({ name });
jobTypes.push(jobType);
}

// Find job type by name
const findJobTypeByName = (name: string): JobType | undefined => {
return jobTypes.find((jobType) => jobType.name === name);
};

// Define postings with associated job types
const postings: Partial<Posting>[] = [
{
title: 'Software Engineer',
Expand All @@ -18,8 +39,8 @@ async function seed() {
jobLink: 'https://www.netflix.com',
salaryStart: 100,
salaryEnd: 150,
jobType: 'Full Stack',
country: 'US',
jobType: findJobTypeByName('Full Stack'),
country: 'USA',
postedDate: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),
},
{
Expand All @@ -29,8 +50,8 @@ async function seed() {
jobLink: 'https://www.google.com',
salaryStart: 120,
salaryEnd: 160,
jobType: 'Front End',
country: 'CA',
jobType: findJobTypeByName('Front End'),
country: 'CAN',
postedDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
},
{
Expand All @@ -40,32 +61,30 @@ async function seed() {
jobLink: 'https://www.amazon.com',
salaryStart: 150,
salaryEnd: 190,
jobType: 'Back End',
country: 'UK',
jobType: findJobTypeByName('Back End'),
country: 'USA',
postedDate: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),
},

{
title: 'Data Scientist',
company: 'Facebook',
companyUrl: 'https://www.facebook.com',
jobLink: 'https://www.facebook.com',
salaryStart: 130,
salaryEnd: 170,
jobType: 'Data',
country: 'US',
jobType: findJobTypeByName('Data'),
country: 'USA',
postedDate: new Date(Date.now() - 9 * 24 * 60 * 60 * 1000).toISOString(),
},

{
title: 'DevOps Engineer',
company: 'Microsoft',
companyUrl: 'https://www.microsoft.com',
jobLink: 'https://www.microsoft.com',
salaryStart: 140,
salaryEnd: 180,
jobType: 'DevOps',
country: 'US',
jobType: findJobTypeByName('Dev Ops'),
country: 'USA',
postedDate: new Date(Date.now() - 17 * 24 * 60 * 60 * 1000).toISOString(),
},
{
Expand All @@ -75,8 +94,8 @@ async function seed() {
jobLink: 'https://www.twitter.com',
salaryStart: 135,
salaryEnd: 175,
jobType: 'AI',
country: 'US',
jobType: findJobTypeByName('AI'),
country: 'USA',
postedDate: new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString(),
},
{
Expand All @@ -86,9 +105,9 @@ async function seed() {
jobLink: 'https://www.spotify.com',
salaryStart: 110,
salaryEnd: 160,
jobType: 'Full Stack',
country: 'US',
postedDate: new Date().toISOString(),
jobType: findJobTypeByName('Full Stack'),
country: 'USA',
postedDate: new Date().toISOString(),
},
{
title: 'Senior Full Stack Developer',
Expand All @@ -97,9 +116,9 @@ async function seed() {
jobLink: 'https://www.airbnb.com',
salaryStart: 130,
salaryEnd: 180,
jobType: 'Full Stack',
country: 'US',
postedDate: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(),
jobType: findJobTypeByName('Full Stack'),
country: 'USA',
postedDate: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(),
},
{
title: 'Backend Software Engineer',
Expand All @@ -108,9 +127,9 @@ async function seed() {
jobLink: 'https://www.uber.com',
salaryStart: 120,
salaryEnd: 170,
jobType: 'Back End',
country: 'US',
postedDate: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),
jobType: findJobTypeByName('Back End'),
country: 'CAN',
postedDate: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),
},
{
title: 'Data Engineer',
Expand All @@ -119,9 +138,9 @@ async function seed() {
jobLink: 'https://www.linkedin.com',
salaryStart: 125,
salaryEnd: 175,
jobType: 'Data',
country: 'US',
postedDate: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),
jobType: findJobTypeByName('Data'),
country: 'USA',
postedDate: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(),
},
{
title: 'AI Research Scientist',
Expand All @@ -130,9 +149,9 @@ async function seed() {
jobLink: 'https://www.openai.com',
salaryStart: 150,
salaryEnd: 200,
jobType: 'AI',
country: 'US',
postedDate: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),
jobType: findJobTypeByName('AI'),
country: 'USA',
postedDate: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(),
},
{
title: 'Senior DevOps Engineer',
Expand All @@ -141,9 +160,9 @@ async function seed() {
jobLink: 'https://www.atlassian.com',
salaryStart: 130,
salaryEnd: 180,
jobType: 'DevOps',
country: 'AU',
postedDate: new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString(),
jobType: findJobTypeByName('Dev Ops'),
country: 'CAN',
postedDate: new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString(),
},
{
title: 'Full Stack JavaScript Developer',
Expand All @@ -152,9 +171,9 @@ async function seed() {
jobLink: 'https://www.slack.com',
salaryStart: 115,
salaryEnd: 165,
jobType: 'Full Stack',
country: 'CA',
postedDate: new Date(Date.now() - 8 * 24 * 60 * 60 * 1000).toISOString(),
jobType: findJobTypeByName('Full Stack'),
country: 'CAN',
postedDate: new Date(Date.now() - 8 * 24 * 60 * 60 * 1000).toISOString(),
},
{
title: 'Backend Java Engineer',
Expand All @@ -163,9 +182,9 @@ async function seed() {
jobLink: 'https://www.oracle.com',
salaryStart: 130,
salaryEnd: 180,
jobType: 'Back End',
country: 'US',
postedDate: new Date(Date.now() - 10 * 24 * 60 * 60 * 1000).toISOString(),
jobType: findJobTypeByName('Back End'),
country: 'USA',
postedDate: new Date(Date.now() - 10 * 24 * 60 * 60 * 1000).toISOString(),
},
{
title: 'Frontend UX/UI Developer',
Expand All @@ -174,9 +193,9 @@ async function seed() {
jobLink: 'https://www.adobe.com',
salaryStart: 110,
salaryEnd: 160,
jobType: 'Front End',
country: 'US',
postedDate: new Date(Date.now() - 12 * 24 * 60 * 60 * 1000).toISOString(),
jobType: findJobTypeByName('Front End'),
country: 'USA',
postedDate: new Date(Date.now() - 12 * 24 * 60 * 60 * 1000).toISOString(),
},
{
title: 'Machine Learning Engineer',
Expand All @@ -185,18 +204,19 @@ async function seed() {
jobLink: 'https://www.ibm.com',
salaryStart: 140,
salaryEnd: 190,
jobType: 'AI',
country: 'US',
jobType: findJobTypeByName('AI'),
country: 'USA',
postedDate: new Date(Date.now() - 15 * 24 * 60 * 60 * 1000).toISOString(),
},
];

// Create postings
for (const posting of postings) {
await postingsService.create(posting);
}

console.log('3 postings have been added!');
console.log('Postings have been added!');
await app.close();
}

seed();
seed();
13 changes: 7 additions & 6 deletions apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { Posting } from './postings/posting.entity';
import { PostingsModule } from './postings/postings.module';
import { JobTypesModule } from './jobtypes/jobtypes.module';

@Module({
imports: [
TypeOrmModule.forRoot({
type: 'sqlite',
database: 'db.sqlite',
entities: [Posting],
synchronize: true, // Set to false in production
type: 'sqlite',
database: 'data.db',
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
synchronize: true,
}),
PostingsModule,
JobTypesModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
export class AppModule {}
14 changes: 14 additions & 0 deletions apps/api/src/jobtypes/jobtype.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Entity, Column, PrimaryGeneratedColumn, OneToMany } from 'typeorm';
import { Posting } from '../postings/posting.entity';

@Entity()
export class JobType {
@PrimaryGeneratedColumn()
id: number;

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

@OneToMany(() => Posting, posting => posting.jobType)
postings: Posting[];
}
60 changes: 60 additions & 0 deletions apps/api/src/jobtypes/jobtypes.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Test, TestingModule } from '@nestjs/testing';
import { JobTypesController } from './jobtypes.controller';
import { JobTypesService } from './jobtypes.service';
import { JobType } from './jobtype.entity';

describe('JobTypesController', () => {
let controller: JobTypesController;
let service: JobTypesService;

const mockJobType = {
id: 1,
name: 'Full Stack',
postings: [],
} as JobType;

const mockJobTypesService = {
findAll: jest.fn().mockResolvedValue([mockJobType]),
findOne: jest.fn().mockResolvedValue(mockJobType),
create: jest.fn().mockResolvedValue(mockJobType),
update: jest.fn().mockResolvedValue(mockJobType),
remove: jest.fn().mockResolvedValue(undefined),
};

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [JobTypesController],
providers: [JobTypesService],
})
.overrideProvider(JobTypesService)
.useValue(mockJobTypesService)
.compile();

controller = module.get<JobTypesController>(JobTypesController);
service = module.get<JobTypesService>(JobTypesService);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});

it('should create a job type', async () => {
expect(await controller.create(mockJobType)).toEqual(mockJobType);
});

it('should find all job types', async () => {
expect(await controller.findAll()).toEqual([mockJobType]);
});

it('should find one job type', async () => {
expect(await controller.findOne('1')).toEqual(mockJobType);
});

it('should update a job type', async () => {
expect(await controller.update('1', mockJobType)).toEqual(mockJobType);
});

it('should delete a job type', async () => {
expect(await controller.remove('1')).toBeUndefined();
});
});
Loading

0 comments on commit c83205d

Please sign in to comment.