Compare commits

1 Commits

Author SHA1 Message Date
derek ba955514f7 Merge pull request 'working' (#44) from working into main
Docker Build and Release Upload / build (push) Successful in 1m44s
Reviewed-on: #44
2025-09-24 03:45:39 +00:00
14 changed files with 76 additions and 216 deletions
+5 -2
View File
@@ -9,13 +9,16 @@ Server:
Update the company rating Update the company rating
JobCleanupService: JobCleanupService:
Need to update notification email to show what job was autoclosed and to follow theme of website | base off company email verify Need to update notification email to show what job and to follow theme of website
CompanyEmailVerify: CompanyEmailVerify:
Need to update notification email to follow theme of website
Create page to notify cx that their work email has been verified Create page to notify cx that their work email has been verified
JobListingController: JobListingController:
Need to work on job filtering more Dont refresh on every filter edit
Line 63 is terrible and need to be fixed in the JobListing DB JobListingController
bools and numbers are getting strigified which breaks the mysql parameters
Validation: Validation:
Alot of the validation is only taking place client side. Alot of the validation is only taking place client side.
+3 -20
View File
@@ -247,7 +247,6 @@
"resolved": "https://registry.npmjs.org/@angular/common/-/common-20.0.3.tgz", "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.0.3.tgz",
"integrity": "sha512-HqqVqaj+xzByWJOIrONVRkpvM6mRuGmC+m9wKixhc9f+xXsymVTBR6xg+G/RwyYP2NuC5chxIZbaJTz2Hj+6+g==", "integrity": "sha512-HqqVqaj+xzByWJOIrONVRkpvM6mRuGmC+m9wKixhc9f+xXsymVTBR6xg+G/RwyYP2NuC5chxIZbaJTz2Hj+6+g==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },
@@ -264,7 +263,6 @@
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.0.3.tgz", "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.0.3.tgz",
"integrity": "sha512-CShPNvqqV5Cleyho8CKtcFlt7l2thHPUdXZPtKHH3Zf43KojvJbJksZLBz6ZbyoQdgxNMYSfbh4h0UbSGtPOzQ==", "integrity": "sha512-CShPNvqqV5Cleyho8CKtcFlt7l2thHPUdXZPtKHH3Zf43KojvJbJksZLBz6ZbyoQdgxNMYSfbh4h0UbSGtPOzQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },
@@ -278,7 +276,6 @@
"integrity": "sha512-u+fYnx1sRrwL0fd8kaAD2LqJjfe/Zj7zyOv0A3Ue7r8jzdNsPU8MWr/QyBaWlqSpPEpR+kD3xmDvRT9ra9RTBA==", "integrity": "sha512-u+fYnx1sRrwL0fd8kaAD2LqJjfe/Zj7zyOv0A3Ue7r8jzdNsPU8MWr/QyBaWlqSpPEpR+kD3xmDvRT9ra9RTBA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/core": "7.27.4", "@babel/core": "7.27.4",
"@jridgewell/sourcemap-codec": "^1.4.14", "@jridgewell/sourcemap-codec": "^1.4.14",
@@ -420,7 +417,6 @@
"resolved": "https://registry.npmjs.org/@angular/core/-/core-20.0.3.tgz", "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.0.3.tgz",
"integrity": "sha512-kB6w1bQgClfmkTbWJeD3vSLqX0e3uSaJD6KJ7XXT1IEaqUs4J+mKRKHQyxpJlpdUb7R+jDaHSM/vrVF15/L2rA==", "integrity": "sha512-kB6w1bQgClfmkTbWJeD3vSLqX0e3uSaJD6KJ7XXT1IEaqUs4J+mKRKHQyxpJlpdUb7R+jDaHSM/vrVF15/L2rA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },
@@ -464,7 +460,6 @@
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.0.3.tgz", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.0.3.tgz",
"integrity": "sha512-cba0bibw9dJ8b+a2a8mwkiq5/HPiakY9P5OiJEVefN+2V/K9CND/pW+KIbW0/P6KhSSDQ29xgcGRseVtkjYLmg==", "integrity": "sha512-cba0bibw9dJ8b+a2a8mwkiq5/HPiakY9P5OiJEVefN+2V/K9CND/pW+KIbW0/P6KhSSDQ29xgcGRseVtkjYLmg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },
@@ -531,7 +526,6 @@
"integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.2.0", "@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
@@ -1423,7 +1417,6 @@
"integrity": "sha512-5AOrZPf2/GxZ+SDRZ5WFplCA2TAQgK3OYrXCYmJL5NaTu4ECcoWFlfUZuw7Es++6Njv7iu/8vpYJhuzxUH76Vg==", "integrity": "sha512-5AOrZPf2/GxZ+SDRZ5WFplCA2TAQgK3OYrXCYmJL5NaTu4ECcoWFlfUZuw7Es++6Njv7iu/8vpYJhuzxUH76Vg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@inquirer/checkbox": "^4.1.6", "@inquirer/checkbox": "^4.1.6",
"@inquirer/confirm": "^5.1.10", "@inquirer/confirm": "^5.1.10",
@@ -3293,7 +3286,6 @@
"integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==", "integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"undici-types": "~7.8.0" "undici-types": "~7.8.0"
} }
@@ -3609,7 +3601,6 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001718", "caniuse-lite": "^1.0.30001718",
"electron-to-chromium": "^1.5.160", "electron-to-chromium": "^1.5.160",
@@ -5551,8 +5542,7 @@
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.7.1.tgz", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.7.1.tgz",
"integrity": "sha512-QnurrtpKsPoixxG2R3d1xP0St/2kcX5oTZyDyQJMY+Vzi/HUlu1kGm+2V8Tz+9lV991leB1l0xcsyz40s9xOOw==", "integrity": "sha512-QnurrtpKsPoixxG2R3d1xP0St/2kcX5oTZyDyQJMY+Vzi/HUlu1kGm+2V8Tz+9lV991leB1l0xcsyz40s9xOOw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT"
"peer": true
}, },
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
@@ -5644,7 +5634,6 @@
"integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@colors/colors": "1.5.0", "@colors/colors": "1.5.0",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
@@ -7494,7 +7483,6 @@
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"dependencies": { "dependencies": {
"tslib": "^2.1.0" "tslib": "^2.1.0"
} }
@@ -7530,7 +7518,6 @@
"integrity": "sha512-sF6TWQqjFvr4JILXzG4ucGOLELkESHL+I5QJhh7CNaE+Yge0SI+ehCatsXhJ7ymU1hAFcIS3/PBpjdIbXoyVbg==", "integrity": "sha512-sF6TWQqjFvr4JILXzG4ucGOLELkESHL+I5QJhh7CNaE+Yge0SI+ehCatsXhJ7ymU1hAFcIS3/PBpjdIbXoyVbg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"chokidar": "^4.0.0", "chokidar": "^4.0.0",
"immutable": "^5.0.2", "immutable": "^5.0.2",
@@ -8285,8 +8272,7 @@
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD", "license": "0BSD"
"peer": true
}, },
"node_modules/tuf-js": { "node_modules/tuf-js": {
"version": "3.0.1", "version": "3.0.1",
@@ -8336,7 +8322,6 @@
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -8503,7 +8488,6 @@
"integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.4.4", "fdir": "^6.4.4",
@@ -8941,8 +8925,7 @@
"version": "0.15.1", "version": "0.15.1",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz",
"integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==", "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==",
"license": "MIT", "license": "MIT"
"peer": true
} }
} }
} }
-6
View File
@@ -11,9 +11,3 @@ export class Application {
public notes: string = ""; public notes: string = "";
public trackUUID: string = crypto.randomUUID(); public trackUUID: string = crypto.randomUUID();
} }
export class ApplicationRequest {
public resumeID: number = 0;
public jobListingID: number = 0;
public responseEmail: string = "";
}
@@ -15,10 +15,11 @@ button {
} }
.top-bar { .top-bar {
display: flex;
flex-wrap: wrap;
break-inside: avoid; break-inside: avoid;
padding: 20px; padding: 20px;
border-radius: 20px; border-radius: 20px;
width: 400px;
margin: 20px; margin: 20px;
background-color: var(--mistox-bg-medium); background-color: var(--mistox-bg-medium);
border: 1px solid var(--mistox-border); border: 1px solid var(--mistox-border);
@@ -30,15 +31,11 @@ button {
display: flex; display: flex;
height: 40px; height: 40px;
align-items: center; align-items: center;
width: 100%;
}
.top-bar-sub h1 {
font-size: 20px;
} }
.top-bar-sub :nth-child(1) { .top-bar-sub :nth-child(1) {
width: 100%; margin: 0;
font-size: 20px;
} }
.top-bar-sub :nth-child(2) { .top-bar-sub :nth-child(2) {
@@ -47,7 +44,6 @@ button {
margin-top: 0; margin-top: 0;
padding: initial; padding: initial;
height: 20px; height: 20px;
width: 100%;
} }
.full-width { .full-width {
@@ -124,9 +120,6 @@ button {
} }
.jobs-per-page { .jobs-per-page {
position: absolute;
bottom: 100px;
right: 0;
display: flex; display: flex;
justify-content: end; justify-content: end;
padding: 20px; padding: 20px;
@@ -139,10 +132,6 @@ button {
font-size: 20px; font-size: 20px;
} }
.jobs-per-page select {
width: 100px;
}
@media (max-width: 1920px) { @media (max-width: 1920px) {
.tile-frame{ .tile-frame{
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
@@ -1,70 +1,43 @@
<div class="tile-frame"> <!-- Filter Bar -->
<div class="top-bar">
<!-- Filter --> <div class="top-bar-sub">
<div class="tile"> <h1>Country</h1>
<div class="top-bar-sub"> <input name="CountryCode" [(ngModel)]="currentFilter.CountryCode" (ngModelChange)="checkUpdate()" type="text" />
<div>
<h1>Country</h1>
</div>
<select name="CountryCode" [(ngModel)]="currentFilter.CountryCode" type="text">
@for(cur of countryOptions; track cur){
<option [value]="cur">{{cur}}</option>
}
</select>
</div>
<div class="top-bar-sub">
<div>
<h1>Postal Code</h1>
</div>
<input name="PostalCode" [(ngModel)]="currentFilter.PostalCode" type="text" />
</div>
@if (currentFilter.CountryCode != null && currentFilter.CountryCode !== "" && currentFilter.PostalCode != null && currentFilter.PostalCode !== ""){
<div class="top-bar-sub">
<div>
<h1>Distance</h1>
</div>
<select name="Distance" [(ngModel)]="currentFilter.Distance" type="number">
@for(cur of distanceOptions; track cur){
<option [value]="cur">{{cur}}</option>
}
</select>
</div>
}
<div class="top-bar-sub">
<div>
<h1>Job Type</h1>
</div>
<select name="JobType" [(ngModel)]="currentFilter.JobType" type="text">
@for(cur of jobTypeOptions; track cur){
<option [value]="cur">{{cur}}</option>
}
</select>
</div>
<div class="top-bar-sub">
<div>
<h1>Minimum Salary</h1>
</div>
<input name="SalaryMin" [(ngModel)]="currentFilter.SalaryMin" type="number" />
</div>
<div class="top-bar-sub">
<div>
<h1>Maximum Salary</h1>
</div>
<input name="SalaryMax" [(ngModel)]="currentFilter.SalaryMax" type="number" />
</div>
<div class="top-bar-sub">
<div>
<h1>Remote</h1>
</div>
<input name="Remote" [(ngModel)]="currentFilter.Remote" type="checkbox" />
</div>
<div class="top-bar-sub">
<h1></h1>
<input name="ApplyButton" style="height: 25px;" value="APPLY" type="button" (click)="reloadFilters()" />
</div>
</div> </div>
<div class="top-bar-sub">
<h1>Postal Code</h1>
<input name="PostalCode" [(ngModel)]="currentFilter.PostalCode" (ngModelChange)="checkUpdate()" type="text" />
</div>
@if (currentFilter.CountryCode != null && currentFilter.CountryCode !== "" && currentFilter.PostalCode != null && currentFilter.PostalCode !== ""){
<div class="top-bar-sub">
<h1>Distance</h1>
<input name="Distance" [(ngModel)]="currentFilter.Distance" type="number" />
</div>
}
<div class="top-bar-sub">
<h1>Job Type</h1>
<input name="CountryCode" [(ngModel)]="currentFilter.JobType" type="text" />
</div>
<div class="top-bar-sub">
<h1>Remote</h1>
<input name="Remote" [(ngModel)]="currentFilter.Remote" type="checkbox" />
</div>
<div class="top-bar-sub">
<h1>Minimum Salary</h1>
<input name="SalaryMin" [(ngModel)]="currentFilter.SalaryMin" type="number" />
</div>
<div class="top-bar-sub">
<h1>Maximum Salary</h1>
<input name="SalaryMax" [(ngModel)]="currentFilter.SalaryMax" type="number" />
</div>
<div class="top-bar-sub">
<h1></h1>
<input name="ApplyButton" style="height: 25px;" value="APPLY" type="button" (click)="reloadFilters()" />
</div>
</div>
<!-- Avaliable Jobs --> <!-- Avaliable Jobs -->
<div class="tile-frame">
@for (cur of JobListingPage; track cur.id){ @for (cur of JobListingPage; track cur.id){
<div class="tile"> <div class="tile">
<div class="tile-title"> <div class="tile-title">
@@ -92,10 +65,5 @@
<div class="jobs-per-page"> <div class="jobs-per-page">
<h1>Jobs Per Page</h1> <h1>Jobs Per Page</h1>
<select name="JobsPerPage" [(ngModel)]="currentFilter.JobsPerPage" (ngModelChange)="reloadFilters()" type="number"> <input name="JobsPerPage" [(ngModel)]="currentFilter.JobsPerPage" (ngModelChange)="reloadFilters()" type="number" />
@for(cur of itemsPerPageOptions; track cur){
<option [value]="cur">{{cur}}</option>
}
</select>
</div> </div>
@@ -16,11 +16,6 @@ import { JobFilter } from 'app/models/JobFilter';
}) })
export class JobsComponent { export class JobsComponent {
public distanceOptions = [10, 25, 50, 100];
public itemsPerPageOptions = [10, 25, 50, 100];
public countryOptions: string[] = [];
public jobTypeOptions: string[] = ["", "Full-time", "Part-time", "Contract", "Temporary", "Internship"];
public currentFilter: JobFilter; public currentFilter: JobFilter;
public JobListingPage: JobListing[] = []; public JobListingPage: JobListing[] = [];
public ErrorMsg: string = ""; public ErrorMsg: string = "";
@@ -41,17 +36,12 @@ export class JobsComponent {
this.ErrorMsg = err.error; this.ErrorMsg = err.error;
} }
}); });
this.http.get<string[]>("/api/location/distinct").subscribe({ }
next: data => {
this.countryOptions = data; checkUpdate(){
this.currentFilter.CountryCode = "US"; if ( this.currentFilter.PostalCode === "" || this.currentFilter.CountryCode === "" ){
}, this.currentFilter.Distance = null;
error: err => { }
this.ErrorMsg = err.error;
}
});
this.currentFilter.JobsPerPage = this.itemsPerPageOptions[0];
this.currentFilter.Distance = this.distanceOptions[0];
} }
reloadFilters(){ reloadFilters(){
@@ -67,7 +57,7 @@ export class JobsComponent {
if (this.currentFilter.CountryCode != null){ if (this.currentFilter.CountryCode != null){
queryBuilder += "&CC=" + this.currentFilter.CountryCode; queryBuilder += "&CC=" + this.currentFilter.CountryCode;
} }
if (this.currentFilter.PostalCode != null && this.currentFilter.CountryCode != null){ if (this.currentFilter.Distance != null){
queryBuilder += "&D=" + this.currentFilter.Distance; queryBuilder += "&D=" + this.currentFilter.Distance;
} }
if (this.currentFilter.JobType != null){ if (this.currentFilter.JobType != null){
@@ -1,7 +1,5 @@
.company-details { .company-details {
background-color: var(--mistox-bg-light); background-color: var(--mistox-bg-light);
flex: 1;
min-width: 650px;
} }
.company-details::after { .company-details::after {
@@ -83,13 +81,8 @@
align-content: center; align-content: center;
} }
.job-frame {
display: flex;
min-height: calc(100vh - 300px);
}
.job-details { .job-details {
flex: 1 1 500px; padding-bottom: 40px;
} }
.job-timestamp { .job-timestamp {
@@ -165,27 +158,3 @@
display: grid; display: grid;
} }
@media (max-width: 1640px) {
.skill-combo {
column-count: 1;
}
}
@media (max-width: 1500px) {
.split {
column-count: 1;
}
}
@media (max-width: 1200px) {
.job-frame {
display: block;
}
}
@@ -67,7 +67,7 @@
<div class="bottom-bar"> <div class="bottom-bar">
@for(resume of myResumes; track resume.trackUUID){ @for(resume of myResumes; track resume.trackUUID){
<button type="button" (click)="applyWithResume(resume)">APPLY USING RESUME: {{ resume.title }}</button> <button type="button" (click)="applyWithResume(resume)">APPLY USING RESUME: {{ resume.name }}</button>
} }
</div> </div>
</div> </div>
@@ -8,7 +8,7 @@ import { Authentication } from 'app/services/Authentication';
import { JobListing } from 'app/models/JobListing'; import { JobListing } from 'app/models/JobListing';
import { Company } from 'app/models/Company'; import { Company } from 'app/models/Company';
import { Resume } from 'app/models/Resume'; import { Resume } from 'app/models/Resume';
import { ApplicationRequest } from 'app/models/Application'; import { Application } from 'app/models/Application';
@Component({ @Component({
selector: 'main-jobs-viewer', selector: 'main-jobs-viewer',
@@ -69,13 +69,18 @@ export class JobViewerComponent {
} }
applyWithResume(resume: Resume) { applyWithResume(resume: Resume) {
var application = new ApplicationRequest; var application = new Application;
if (this.auth.loggedInUser.id != null){
application.accountID = this.auth.loggedInUser.id;
}
if (resume.id != null){ if (resume.id != null){
application.resumeID = resume.id; application.resumeID = resume.id;
} }
application.jobListingID = this.JobListingID; application.jobListingID = this.JobListingID;
application.hasBeenViewed = false;
application.responseEmail = resume.email; application.responseEmail = resume.email;
this.http.post("api/application", application).subscribe({ this.http.post("api/application", application).subscribe({
@@ -28,21 +28,13 @@ namespace BoredCareers.Controllers {
} }
[HttpPost] [HttpPost]
public async Task<IActionResult> SetApplication([FromBody] ApplicationRequest appReq) { public async Task<IActionResult> SetApplication([FromBody] Application application) {
if (isLoggedIn()) { if (isLoggedIn()) {
Application application = new Application() { if (application.AccountID == getLoggedInUserID()) {
AccountID = getLoggedInUserID(), await _databaseService.SetApplication(application);
DateApplied = DateTime.UtcNow, return Ok();
JobListingID = appReq.JobListingID, }
ResumeID = appReq.ResumeID, return NotFound("Cannot apply for someone else");
ResponseEmail = appReq.ResponseEmail,
HasBeenViewed = false,
ResponseStatus = "",
Notes = "",
Rating = -1
};
await _databaseService.SetApplication(application);
return Ok();
} }
return NotFound("Not logged in"); return NotFound("Not logged in");
} }
@@ -18,14 +18,5 @@ namespace BoredCareers.Controllers {
return NotFound("Not logged in"); return NotFound("Not logged in");
} }
[HttpGet("Distinct")]
public async Task<IActionResult> GetCountries() {
if (isLoggedIn()) {
string[] places = await _databaseService.GetDistinctCountries();
return Ok(places.ToArray());
}
return NotFound("Not logged in");
}
} }
} }
-6
View File
@@ -11,10 +11,4 @@ namespace BoredCareers.Entities {
public int Rating { get; set; } public int Rating { get; set; }
public string Notes { get; set; } = ""; public string Notes { get; set; } = "";
} }
public class ApplicationRequest {
public int ResumeID { get; set; } // FK
public int JobListingID { get; set; } // FK
public string ResponseEmail { get; set; } = "";
}
} }
@@ -62,23 +62,5 @@ namespace BoredCareers.Services.DatabaseService {
return closePostalCodes.ToArray(); return closePostalCodes.ToArray();
} }
public async Task<string[]> GetDistinctCountries() {
List<string> closePostalCodes = new List<string>();
using (MySqlConnection connection = GetConnection()) {
await connection.OpenAsync();
string command = "SELECT DISTINCT(CountryCode) FROM PostalCodes;";
MySqlCommand cmd = new MySqlCommand(command, connection);
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
while (await reader.ReadAsync()) {
string _city = reader.GetString("CountryCode");
closePostalCodes.Add(_city);
}
}
}
return closePostalCodes.ToArray();
}
} }
} }
@@ -21,12 +21,12 @@ namespace BoredCareers.Services {
</div> </div>
<div style=""padding: 20px; text-align: left; font-size: 16px; color: oklch(.76 .1 264);""> <div style=""padding: 20px; text-align: left; font-size: 16px; color: oklch(.76 .1 264);"">
<p>Hi @CompanyName,</p> <p>Hi @CompanyName,</p>
<p>Thank you for connecting your company to our service</p> <p>Thank you for making an account with us</p>
<p>In order to start listing opportunities we need to verify your email address by clicking the link below:</p> <p>In order to start using your account we need to verify your email address by clicking the link below:</p>
<p style=""text-align: center;""> <p style=""text-align: center;"">
<a href=""https://boredcareers.com/api/company/verifyemail?CompanyID=@ID&EmailToken=@VerifyPassword"" style=""background-color: oklch(.76 .13 84); color: #ffffff; text-decoration: none; padding: 15px 25px; font-size: 16px; border-radius: 5px; display: inline-block;"">Verify Email</a> <a href=""https://boredcareers.com/api/company/verifyemail?CompanyID=@ID&EmailToken=@VerifyPassword"" style=""background-color: oklch(.76 .13 84); color: #ffffff; text-decoration: none; padding: 15px 25px; font-size: 16px; border-radius: 5px; display: inline-block;"">Verify Email</a>
</p> </p>
<p>If you didn't link a company to your account please ignore this email.</p> <p>If you didn't create an account please ignore this email.</p>
<p>Best regards</p> <p>Best regards</p>
</div> </div>
<div style=""padding: 10px; text-align: center; background-color: oklch(.15 .065 264); color: #888888; font-size: 12px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;""> <div style=""padding: 10px; text-align: center; background-color: oklch(.15 .065 264); color: #888888; font-size: 12px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;"">