diff --git a/ToDo.yaml b/ToDo.yaml index 80938c7..ca253bb 100755 --- a/ToDo.yaml +++ b/ToDo.yaml @@ -2,10 +2,17 @@ Server: Emails: Dont follow theme of website + When a company is created: + Send email -> verify ownership of the email + Need to timeout email reset tokens: Client: - + jobs/new: + When remote job is check'd it still asks for location information + Want to add Required skills to help with filtering + Need to fix some UI bugs. + Want to add completed job listing preview at end of carosel database: Add Applied Jobs Table \ No newline at end of file diff --git a/database/mistox.sql b/database/mistox.sql index a16ece7..995ee57 100755 --- a/database/mistox.sql +++ b/database/mistox.sql @@ -205,14 +205,14 @@ INSERT INTO Account ( DataServer ) VALUES ( 1, - `admin`, - `admin@mistox.com`, + 'admin', + 'admin@mistox.com', 1, - `$2a$11$0UeWLLqTXe3FG161QVuI0OQJ9rulspUpMG581DI6KSzDXBbFKd00S`, + '$2a$11$0UeWLLqTXe3FG161QVuI0OQJ9rulspUpMG581DI6KSzDXBbFKd00S', 0, 5, 0, - `Admin`, - ``, - `` + 'Admin', + '', + '' ); \ No newline at end of file diff --git a/src/Client/angular.json b/src/Client/angular.json index bf33e66..c593301 100644 --- a/src/Client/angular.json +++ b/src/Client/angular.json @@ -93,5 +93,8 @@ } } } + }, + "cli": { + "analytics": false } } diff --git a/src/Client/src/app/app.html b/src/Client/src/app/app.html index 17d70fc..61c0b51 100644 --- a/src/Client/src/app/app.html +++ b/src/Client/src/app/app.html @@ -1,8 +1,8 @@
HOME - COMPANIES JOB BOARD + RESUMES
CONTACT PRIVACY + ABOUT
\ No newline at end of file diff --git a/src/Client/src/app/pages/legal/about/about.component.ts b/src/Client/src/app/pages/legal/about/about.component.ts index 633ccb3..24cb909 100644 --- a/src/Client/src/app/pages/legal/about/about.component.ts +++ b/src/Client/src/app/pages/legal/about/about.component.ts @@ -8,6 +8,7 @@ import { CommonModule } from '@angular/common'; @Component({ selector: 'legal-about', templateUrl: './about.component.html', + styleUrls: [ './about.component.css' ], imports: [ FormsModule, CommonModule ] }) export class AboutComponent { diff --git a/src/Client/src/app/pages/home/home.component.css b/src/Client/src/app/pages/legal/contact/contact.component.css similarity index 100% rename from src/Client/src/app/pages/home/home.component.css rename to src/Client/src/app/pages/legal/contact/contact.component.css diff --git a/src/Client/src/app/pages/home/home.component.html b/src/Client/src/app/pages/legal/contact/contact.component.html similarity index 100% rename from src/Client/src/app/pages/home/home.component.html rename to src/Client/src/app/pages/legal/contact/contact.component.html diff --git a/src/Client/src/app/pages/project/mist/mist.component.ts b/src/Client/src/app/pages/legal/contact/contact.component.ts similarity index 70% rename from src/Client/src/app/pages/project/mist/mist.component.ts rename to src/Client/src/app/pages/legal/contact/contact.component.ts index 3296237..eaa44cf 100644 --- a/src/Client/src/app/pages/project/mist/mist.component.ts +++ b/src/Client/src/app/pages/legal/contact/contact.component.ts @@ -6,14 +6,15 @@ import { Title } from '@angular/platform-browser'; import { CommonModule } from '@angular/common'; @Component({ - selector: 'project-mist', - templateUrl: './mist.component.html', + selector: 'legal-contact', + templateUrl: './contact.component.html', + styleUrls: [ './contact.component.css' ], imports: [ FormsModule, CommonModule ] }) -export class MistComponent { +export class ContactComponent { constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title ) { - this.title.setTitle("Mist | Mistox"); + this.title.setTitle("Contact | BoredCareers"); }; - + } \ No newline at end of file diff --git a/src/Client/src/app/pages/legal/privacy/privacy.component.css b/src/Client/src/app/pages/legal/privacy/privacy.component.css new file mode 100644 index 0000000..26081b8 --- /dev/null +++ b/src/Client/src/app/pages/legal/privacy/privacy.component.css @@ -0,0 +1,15 @@ +.center { + background-color: green; +} + +.tile-frame { + column-count: 4; + column-gap: 20px; + padding: 20px; + width: calc(100% - 40px); +} + +.tile{ + background-color: aqua; + height: 40px; +} \ No newline at end of file diff --git a/src/Client/src/app/pages/legal/privacy/privacy.component.html b/src/Client/src/app/pages/legal/privacy/privacy.component.html new file mode 100644 index 0000000..29da843 --- /dev/null +++ b/src/Client/src/app/pages/legal/privacy/privacy.component.html @@ -0,0 +1,11 @@ +
+ +
+ +
+ +
+ +
+ +
\ No newline at end of file diff --git a/src/Client/src/app/pages/legal/privacy/privacy.component.ts b/src/Client/src/app/pages/legal/privacy/privacy.component.ts new file mode 100644 index 0000000..9543545 --- /dev/null +++ b/src/Client/src/app/pages/legal/privacy/privacy.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; +import { Title } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; + +@Component({ + selector: 'legal-privacy', + templateUrl: './privacy.component.html', + styleUrls: [ './privacy.component.css' ], + imports: [ FormsModule, CommonModule ] +}) +export class PrivacyComponent { + + constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title ) { + this.title.setTitle("Privacy | BoredCareers"); + }; + +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/company/connect/companyconnect.component.css b/src/Client/src/app/pages/main/company/connect/companyconnect.component.css new file mode 100644 index 0000000..4203dc9 --- /dev/null +++ b/src/Client/src/app/pages/main/company/connect/companyconnect.component.css @@ -0,0 +1,93 @@ +.title-text { + width: 100%; + text-align: center; +} + +form { + display: grid; + grid-template-areas: "stack"; + position: relative; + width: 100%; + overflow: hidden; + transition: 0.5s; +} + +.center { + width: 100%; + display: grid; + justify-content: center; +} + +.sub-frame { + position: relative; + grid-area: stack; + transition: 0.5s; + width: 100%; + text-align: center; +} + +.content-frame { + background-color: #00000088; + border-radius: 10px; + padding: 40px; + break-inside: avoid; + margin-bottom: 20px; +} + +.footer-frame { + background-color: #00000044; + border-radius: 10px; + padding: 10px; + break-inside: avoid; + margin-bottom: 20px; +} + +.split { + column-count: 2; +} + +.half-frame { + width: 400px; + break-inside: avoid; +} + +.content-frame label { + color: #FFF; +} + +.content-frame textarea { + width: calc(100% - 40px); + margin: 0 20px; + height: 200px; + resize: none; +} + +.content-frame input { + width: calc(50% - 24px); + margin: 0 calc(25% + 10px); + margin-bottom: 20px; + appearance: textfield; +} + +.content-frame input:focus ~ label { + color: green; +} + +.content-frame select { + width: calc(50% - 24px); + margin: 0 calc(25% + 10px); + margin-bottom: 20px; +} + +.tile-frame { + column-count: 4; + column-gap: 20px; + padding: 20px; + width: calc(100% - 40px); +} + +.tile{ + background-color: var(--Mistox-Dark)\); + height: 40px; + break-inside: avoid; +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/company/connect/companyconnect.component.html b/src/Client/src/app/pages/main/company/connect/companyconnect.component.html new file mode 100644 index 0000000..12111ca --- /dev/null +++ b/src/Client/src/app/pages/main/company/connect/companyconnect.component.html @@ -0,0 +1,147 @@ +
+

Connect To Company

+
+
+ +
+
+
+ + + +
+ +
+
+ + +
+
+
+ + + + +
+ +
+
+ + +
+
+
+ + + + +
+ +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+

Job Location

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+
+
+ + +
+
+
+ + + + +
+
+
+ + +
+
+
+ {{ newListing.name }} + +
+
+
+ city: {{ newListing.city }} +
+
+ country: {{ newListing.country }} +
+
+
+
+ state: {{ newListing.stateOrRegion }} +
+
+ postal code: {{ newListing.postalCode }} +
+
+
+ {{ newListing.description }} +
+
+
+ + +
+
+
+
\ No newline at end of file diff --git a/src/Client/src/app/pages/main/company/connect/companyconnect.component.ts b/src/Client/src/app/pages/main/company/connect/companyconnect.component.ts new file mode 100644 index 0000000..2bb7cb7 --- /dev/null +++ b/src/Client/src/app/pages/main/company/connect/companyconnect.component.ts @@ -0,0 +1,77 @@ +import { Component, ElementRef, QueryList, ViewChildren } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { Router, ActivatedRoute, RouterModule } from '@angular/router'; +import { Title } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; +import { Authentication } from 'app/services/Authentication'; +import { Company } from 'app/models/Company'; + +@Component({ + selector: 'main-company-connect', + templateUrl: './companyconnect.component.html', + styleUrls: [ './companyconnect.component.css' ], + imports: [ FormsModule, CommonModule, RouterModule ] +}) +export class CompanyConnectComponent { + + @ViewChildren('step') formSteps!: QueryList>; + currentStep: number = 0; + + public newListing: Company = new Company(); + public ErrorMsg: string = ""; + + constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title, public auth: Authentication ) { + this.title.setTitle("Company - Connect | BoredCareers"); + }; + + ngAfterViewInit(){ + this.formSteps.forEach((step: ElementRef, i: number) => { + if (i === this.currentStep) { + step.nativeElement.style.left = '0%'; + } else if (i < this.currentStep) { + step.nativeElement.style.left = '-100%'; + } else { + step.nativeElement.style.left = '100%'; + } + }); + } + + nextStep(){ + this.currentStep += 1; + this.formSteps.forEach((step: ElementRef, i: number) => { + if (i === this.currentStep) { + step.nativeElement.style.left = '0%'; + } else if (i < this.currentStep) { + step.nativeElement.style.left = '-100%'; + } else { + step.nativeElement.style.left = '100%'; + } + }); + } + + prevStep(){ + this.currentStep -= 1; + this.formSteps.forEach((step: ElementRef, i: number) => { + if (i === this.currentStep) { + step.nativeElement.style.left = '0%'; + } else if (i < this.currentStep) { + step.nativeElement.style.left = '-100%'; + } else { + step.nativeElement.style.left = '100%'; + } + }); + } + + PostNewCompany(company: Company){ + this.http.post("api/company?newCompany=true", company).subscribe({ + next: data => { + this.router.navigate([""]); + }, + error: err => { + alert("Failed to create the job listing. Err: " + err.error); + } + }); + } + +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/home/home.component.css b/src/Client/src/app/pages/main/home/home.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/Client/src/app/pages/main/home/home.component.html b/src/Client/src/app/pages/main/home/home.component.html new file mode 100644 index 0000000..e69de29 diff --git a/src/Client/src/app/pages/home/home.component.ts b/src/Client/src/app/pages/main/home/home.component.ts similarity index 96% rename from src/Client/src/app/pages/home/home.component.ts rename to src/Client/src/app/pages/main/home/home.component.ts index 6d409fd..478962e 100644 --- a/src/Client/src/app/pages/home/home.component.ts +++ b/src/Client/src/app/pages/main/home/home.component.ts @@ -6,7 +6,7 @@ import { Title } from '@angular/platform-browser'; import { CommonModule } from '@angular/common'; @Component({ - selector: 'home', + selector: 'main-home', templateUrl: './home.component.html', styleUrls: [ './home.component.css' ], imports: [ FormsModule, CommonModule ] diff --git a/src/Client/src/app/pages/main/jobs/edit/jobedit.component.css b/src/Client/src/app/pages/main/jobs/edit/jobedit.component.css new file mode 100644 index 0000000..9d97a2c --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/edit/jobedit.component.css @@ -0,0 +1,12 @@ +.tile-frame { + column-count: 4; + column-gap: 20px; + padding: 20px; + width: calc(100% - 40px); +} + +.tile{ + background-color: var(--Mistox-Dark)\); + height: 40px; + break-inside: avoid; +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/jobs/edit/jobedit.component.html b/src/Client/src/app/pages/main/jobs/edit/jobedit.component.html new file mode 100644 index 0000000..05e4dca --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/edit/jobedit.component.html @@ -0,0 +1,16 @@ +
+
+

{{ cur.title }}

+

{{ cur.jobType }}

+

Is Remote: {{ cur.remote }}

+

{{ cur.salaryMin }}

+

{{ cur.salaryMax }}

+

{{ cur.city }}

+

{{ cur.stateOrRegion }}

+

{{ cur.country }}

+

{{ cur.postalCode }}

+

{{ cur.description }}

+

Posted: {{ cur.createdTime }}

+

Modified: {{ cur.modifiedTime }}

+
+
\ No newline at end of file diff --git a/src/Client/src/app/pages/main/jobs/edit/jobedit.component.ts b/src/Client/src/app/pages/main/jobs/edit/jobedit.component.ts new file mode 100644 index 0000000..35075b9 --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/edit/jobedit.component.ts @@ -0,0 +1,53 @@ +import { Component } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { Router, ActivatedRoute, RouterModule } from '@angular/router'; +import { Title } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; +import { JobListing } from 'app/models/JobListing'; +import { Authentication } from 'app/services/Authentication'; + +@Component({ + selector: 'main-jobs-edit', + templateUrl: './jobedit.component.html', + styleUrls: [ './jobedit.component.css' ], + imports: [ FormsModule, CommonModule, RouterModule ] +}) +export class JobEditComponent { + + public MyJobListings: JobListing[] = []; + public JobListingPage: JobListing[] = []; + public ErrorMsg: string = ""; + + public Page: number = 1; + + constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title, public auth: Authentication ) { + this.title.setTitle("Jobs - edit | BoredCareers"); + + if (this.Page == 1){ + + } + + http.get("api/joblisting?PageQuantity=" + 10 + "&Page=" + 1).subscribe({ + next: data => { + this.JobListingPage = data; + }, + error: err => { + this.ErrorMsg = err.error; + } + }); + + }; + + RemoveJobListing( JobListingID: number ){ + this.http.delete("api/joblisting?JobListingID=" + JobListingID).subscribe({ + next: data => { + window.location.reload(); + }, + error: err => { + alert("Failed to delete the job listing. Try again"); + } + }); + } + +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/jobs/jobs.component.css b/src/Client/src/app/pages/main/jobs/jobs.component.css new file mode 100644 index 0000000..9d97a2c --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/jobs.component.css @@ -0,0 +1,12 @@ +.tile-frame { + column-count: 4; + column-gap: 20px; + padding: 20px; + width: calc(100% - 40px); +} + +.tile{ + background-color: var(--Mistox-Dark)\); + height: 40px; + break-inside: avoid; +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/jobs/jobs.component.html b/src/Client/src/app/pages/main/jobs/jobs.component.html new file mode 100644 index 0000000..5c422ac --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/jobs.component.html @@ -0,0 +1,42 @@ + +
+
+
+

{{ cur.title }}

+

{{ cur.jobType }}

+

Is Remote: {{ cur.remote }}

+

{{ cur.salaryMin }}

+

{{ cur.salaryMax }}

+

{{ cur.city }}

+

{{ cur.stateOrRegion }}

+

{{ cur.country }}

+

{{ cur.postalCode }}

+

{{ cur.description }}

+

Posted: {{ cur.createdTime }}

+

Modified: {{ cur.modifiedTime }}

+
+ + +
+
+ +
+
+ + +
+
+

{{ cur.title }}

+

{{ cur.jobType }}

+

Is Remote: {{ cur.remote }}

+

{{ cur.salaryMin }}

+

{{ cur.salaryMax }}

+

{{ cur.city }}

+

{{ cur.stateOrRegion }}

+

{{ cur.country }}

+

{{ cur.postalCode }}

+

{{ cur.description }}

+

Posted: {{ cur.createdTime }}

+

Modified: {{ cur.modifiedTime }}

+
+
\ No newline at end of file diff --git a/src/Client/src/app/pages/main/jobs/jobs.component.ts b/src/Client/src/app/pages/main/jobs/jobs.component.ts new file mode 100644 index 0000000..336d4ef --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/jobs.component.ts @@ -0,0 +1,53 @@ +import { Component } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { Router, ActivatedRoute, RouterModule } from '@angular/router'; +import { Title } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; +import { JobListing } from 'app/models/JobListing'; +import { Authentication } from 'app/services/Authentication'; + +@Component({ + selector: 'main-jobs', + templateUrl: './jobs.component.html', + styleUrls: [ './jobs.component.css' ], + imports: [ FormsModule, CommonModule, RouterModule ] +}) +export class JobsComponent { + + public MyJobListings: JobListing[] = []; + public JobListingPage: JobListing[] = []; + public ErrorMsg: string = ""; + + public Page: number = 1; + + constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title, public auth: Authentication ) { + this.title.setTitle("Jobs | BoredCareers"); + + if (this.Page == 1){ + + } + + http.get("api/joblisting?PageQuantity=" + 10 + "&Page=" + 1).subscribe({ + next: data => { + this.JobListingPage = data; + }, + error: err => { + this.ErrorMsg = err.error; + } + }); + + }; + + RemoveJobListing( JobListingID: number ){ + this.http.delete("api/joblisting?JobListingID=" + JobListingID).subscribe({ + next: data => { + window.location.reload(); + }, + error: err => { + alert("Failed to delete the job listing. Try again"); + } + }); + } + +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/jobs/new/jobnew.component.css b/src/Client/src/app/pages/main/jobs/new/jobnew.component.css new file mode 100644 index 0000000..3606281 --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/new/jobnew.component.css @@ -0,0 +1,84 @@ +.title-text { + width: 100%; + text-align: center; +} + +form { + display: grid; + grid-template-areas: "stack"; + position: relative; + width: 100%; + overflow: hidden; + transition: 0.5s; +} + +.center { + width: 100%; + display: flex; + justify-content: center; +} + +.sub-frame { + position: relative; + grid-area: stack; + transition: 0.5s; + width: 100%; + text-align: center; +} + +.content-frame { + background-color: #00000088; + border-radius: 10px; + padding: 40px; + break-inside: avoid; +} + +.split { + column-count: 2; +} + +.half-frame { + width: 400px; + break-inside: avoid; +} + +.content-frame label { + color: #FFF; +} + +.content-frame textarea { + width: calc(100% - 40px); + margin: 0 20px; + height: 200px; + resize: none; +} + +.content-frame input { + width: calc(50% - 24px); + margin: 0 calc(25% + 10px); + margin-bottom: 20px; + appearance: textfield; +} + +.content-frame input:focus ~ label { + color: green; +} + +.content-frame select { + width: calc(50% - 24px); + margin: 0 calc(25% + 10px); + margin-bottom: 20px; +} + +.tile-frame { + column-count: 4; + column-gap: 20px; + padding: 20px; + width: calc(100% - 40px); +} + +.tile{ + background-color: var(--Mistox-Dark)\); + height: 40px; + break-inside: avoid; +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/jobs/new/jobnew.component.html b/src/Client/src/app/pages/main/jobs/new/jobnew.component.html new file mode 100644 index 0000000..949fd56 --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/new/jobnew.component.html @@ -0,0 +1,108 @@ +
+

POST A NEW JOB

+
+
+ +
+
+
+ + + +
+
+
+ + +
+
+
+
+ + +
+
+ + +
+ + +
+
+
+ + +
+
+

Job Location

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+
+
+ + +
+

Salary Range

+
+
+
+ + +
+
+ + +
+ + +
+
+
+ + +
+
+
+ + + + +
+
+
+ + +
+
+
+ + +
+
+
+
\ No newline at end of file diff --git a/src/Client/src/app/pages/main/jobs/new/jobnew.component.ts b/src/Client/src/app/pages/main/jobs/new/jobnew.component.ts new file mode 100644 index 0000000..0d8a586 --- /dev/null +++ b/src/Client/src/app/pages/main/jobs/new/jobnew.component.ts @@ -0,0 +1,77 @@ +import { Component, ElementRef, QueryList, ViewChildren } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { Router, ActivatedRoute, RouterModule } from '@angular/router'; +import { Title } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; +import { JobListing } from 'app/models/JobListing'; +import { Authentication } from 'app/services/Authentication'; + +@Component({ + selector: 'main-jobs-new', + templateUrl: './jobnew.component.html', + styleUrls: [ './jobnew.component.css' ], + imports: [ FormsModule, CommonModule, RouterModule ] +}) +export class JobNewComponent { + + @ViewChildren('step') formSteps!: QueryList>; + currentStep: number = 0; + + public newListing: JobListing = new JobListing(); + public ErrorMsg: string = ""; + + constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title, public auth: Authentication ) { + this.title.setTitle("Jobs - new | BoredCareers"); + }; + + ngAfterViewInit(){ + this.formSteps.forEach((step: ElementRef, i: number) => { + if (i === this.currentStep) { + step.nativeElement.style.left = '0%'; + } else if (i < this.currentStep) { + step.nativeElement.style.left = '-100%'; + } else { + step.nativeElement.style.left = '100%'; + } + }); + } + + nextStep(){ + this.currentStep += 1; + this.formSteps.forEach((step: ElementRef, i: number) => { + if (i === this.currentStep) { + step.nativeElement.style.left = '0%'; + } else if (i < this.currentStep) { + step.nativeElement.style.left = '-100%'; + } else { + step.nativeElement.style.left = '100%'; + } + }); + } + + prevStep(){ + this.currentStep -= 1; + this.formSteps.forEach((step: ElementRef, i: number) => { + if (i === this.currentStep) { + step.nativeElement.style.left = '0%'; + } else if (i < this.currentStep) { + step.nativeElement.style.left = '-100%'; + } else { + step.nativeElement.style.left = '100%'; + } + }); + } + + PostJobListing(jobListing: JobListing){ + this.http.post("api/joblisting", jobListing).subscribe({ + next: data => { + + }, + error: err => { + alert("Failed to create the job listing. Try again"); + } + }); + } + +} \ No newline at end of file diff --git a/src/Client/src/app/pages/main/resumes/resumes.component.css b/src/Client/src/app/pages/main/resumes/resumes.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/Client/src/app/pages/main/resumes/resumes.component.html b/src/Client/src/app/pages/main/resumes/resumes.component.html new file mode 100644 index 0000000..196d036 --- /dev/null +++ b/src/Client/src/app/pages/main/resumes/resumes.component.html @@ -0,0 +1,13 @@ +
+
+

{{ cur.name }}

+

{{ cur.field }}

+

{{ cur.email }}

+

{{ cur.phoneNumber }}

+

{{ cur.city }}

+

{{ cur.stateOrRegion }}

+

{{ cur.country }}

+

{{ cur.postalCode }}

+

Active: {{ cur.isActive }}

+
+
\ No newline at end of file diff --git a/src/Client/src/app/pages/main/resumes/resumes.component.ts b/src/Client/src/app/pages/main/resumes/resumes.component.ts new file mode 100644 index 0000000..75cba38 --- /dev/null +++ b/src/Client/src/app/pages/main/resumes/resumes.component.ts @@ -0,0 +1,24 @@ +import { Component } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; +import { Title } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; +import { Resume } from 'app/models/Resume'; + +@Component({ + selector: 'main-resumes', + templateUrl: './resumes.component.html', + styleUrls: [ './resumes.component.css' ], + imports: [ FormsModule, CommonModule ] +}) +export class ResumesComponent { + + public ResumePage: Resume[] = []; + + constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title ) { + this.title.setTitle("Resumes | BoredCareers"); + + }; + +} \ No newline at end of file diff --git a/src/Client/src/app/pages/project/mist/mist.component.html b/src/Client/src/app/pages/project/mist/mist.component.html deleted file mode 100644 index 86ec944..0000000 --- a/src/Client/src/app/pages/project/mist/mist.component.html +++ /dev/null @@ -1,18 +0,0 @@ -
-
-

What is the game

-

Project-Mist is a survival game. Kind of like a battle royal in a sense but, think of it backwards. And no I know what your thinking. Its not the first person to die wins. No instead its a never ending survival game where you can free roam and build structures. The catch is, the person who has the highest stats [i.e A combination of kills, survival time] has a marker placed on their forhead.

-

How will the game play

-

When you join the game you will be able to customize your character. There you can set a default loadout for your player. This will be the spawn weapon and gear. After that you will drop into the map with other players to fend for your life. The kill-leader will be marked loosely on the mini-map. You can choose to go after the kill leader or you can choose to loot first. The choice is yours. But be aware that if you survive long enough you will become the new kill leader.

-

Current Idea Board *SUBJECT TO CHANGE*

-

Survival Game
look at item to pick up 'e' for third person and click for third [No nearby]
normal weapons with bullet drop bullet travel time
snipers but rare [Maybe special]

-

Abilities selectable at spawn
a max 20 credit slider where you can spend them on traits
Stamina -> run for longer distances
Strength -> carry more weight
Vitality -> Have more base health
Stealth -> Approximate location on map is bigger

-

More weight slows player some
Backpacks -> Add slots but not weight

-

Oddball style game
Map that shows the relitive area of the top player

-

spawn with classes
2 mags
no attachments
unlock guns with experience

-

no health regen
final hit headshots = 20 credits
final hit bodyshots = 10 credits

-

classes require credits to spawn with better stuff
inventory and credits are transferrable between servers and sessions
combat loggging - if leave in combat start from scratch
one dynamicly roaming entity of the night ( Impossible to kill, when near heart starts pumping and vinegrette )
goes after people possible to get away
Dyanmic day and night cycle
Dynamic weather ( rain, fog, thunder, lightning )
floods that cause roaring rivers to fill that cannot be swam
Fires that char trees(no leaves), regrows in 3ish days
Master leaderboard in the main menu of top players per rank
Ranked lobby ( Disabled until player base )
small towns around a main centralized area( ie city or temple )
large servers
random spawned skin boxes that require credits to open
purchasable skins
bullet penatration on certain materials
bullet reflection on certain materials
No kill leader until you get at least 2 kills minimum

-

Tournament mode
all players spawn at the same time
hold oddball for 30mins total

-

server quits introducing people into game after 5 hrs. (last man standing mode)
last person in server wins
on death quit to new server
everyone becomes oddball
less players alive equal less oddball area

-
-
\ No newline at end of file diff --git a/src/Client/src/app/pages/store/admin/edititem/edit.component.html b/src/Client/src/app/pages/store/admin/edititem/edit.component.html deleted file mode 100644 index c7ae0fb..0000000 --- a/src/Client/src/app/pages/store/admin/edititem/edit.component.html +++ /dev/null @@ -1,50 +0,0 @@ -
-
-
-

Edit Item

- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
-
- -
- -
-
- -
-
- -
    -
  • {{ msg }}
  • -
-
- - -
-
- - Image Preview -
-
-
-
\ No newline at end of file diff --git a/src/Client/src/app/pages/store/admin/edititem/edit.component.ts b/src/Client/src/app/pages/store/admin/edititem/edit.component.ts deleted file mode 100644 index 272fefc..0000000 --- a/src/Client/src/app/pages/store/admin/edititem/edit.component.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { Component, ElementRef, ViewChild } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { FormsModule } from '@angular/forms'; -import { Router, ActivatedRoute } from '@angular/router'; -import { Title } from '@angular/platform-browser'; -import { CommonModule } from '@angular/common'; -import { Authentication } from '../../../../services/Authentication'; -import { Product } from 'app/models/Product'; - -@Component({ - selector: 'item-edit', - templateUrl: './edit.component.html', - imports: [ FormsModule, CommonModule ] -}) -export class EditItemComponent { - @ViewChild('FileUpload') InputDOM!: ElementRef; - - readonly maxFileMB = 16; - - newItem: Product = new Product(); - errorMsgs: string[] = []; - - constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title, public auth: Authentication ) { - this.title.setTitle("Edit | ADMIN"); - this.route.queryParams.subscribe(params => { - this.newItem.id = params['ProductID'] || ''; - }); - - // If user is not logged in -> route home - if (!auth.isLoggedIn){ - router.navigate(["/"]); - } - - // If user is not Admin -> route home - if (auth.loggedInUser.siteData.role != "Admin"){ - router.navigate(["/"]); - } - - // Load product - const formData = new FormData(); - formData.append("productID", this.newItem.id.toString()); - this.http.post( "api/product/get", formData ).subscribe({ - next: async (data) => { - this.newItem = data; - this.newItem.images.forEach(img => { - http.get("api/productimage/get?ProductID=" + img.productID + "&ImageID=" + img.imageID, { responseType: 'blob' }).subscribe(blob => { - img.imageSrc = URL.createObjectURL(blob); - this.imagePreviews.push(img.imageSrc); - this.selectedFiles.push(new File([blob], "EmptyName", {type: "image/jpeg"})); - }); - }); - }, - error: err => { - console.log("Err loading product: ", err); - } - }); - }; - - sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - - selectedFiles: File[] = []; - imagePreviews: string[] = []; - onFileSelected(event: Event){ - const fileInput = event.target as HTMLInputElement; - - if (!fileInput.files?.length){ - return; - } - - for (let i=0; i this.maxFileMB * 1024 * 1024){ - this.errorMsgs.push("File exceeds max file size of 16MB"); - continue; - } - // No issues add file to the list - this.selectedFiles.push( file ); - - const reader = new FileReader(); - reader.onload= () => { - this.imagePreviews.push(reader.result as string); - } - reader.readAsDataURL(file); - - this.InputDOM.nativeElement.value = ''; - } - } - - RemovePhoto(imagePreview: string){ - let i = this.imagePreviews.indexOf(imagePreview); - this.imagePreviews.splice(i, 1); - this.selectedFiles.splice(i, 1); - } - - onSubmit(){ - const formData = new FormData(); - // Append non-file fields - formData.append("Name", this.newItem.name); - formData.append("Description", this.newItem.description); - formData.append("Cost", this.newItem.cost.toString()); - formData.append("Url", this.newItem.url); - - // Add image fileds - if (this.selectedFiles.length > 0){ - for(let i=0; i( "api/product/create", formData ).subscribe({ - next: async (data) => { - if (data == true){ - this.errorMsgs = ["Product Created Successfully"]; - await this.sleep(3000); - this.router.navigate(["/catalog"]); - }else{ - this.errorMsgs = ["Error has ocurred"]; - } - }, - error: err => { - console.log("New Product Err: ", err); - } - }); - } -} \ No newline at end of file diff --git a/src/Client/src/app/pages/store/admin/newitem/new.component.html b/src/Client/src/app/pages/store/admin/newitem/new.component.html deleted file mode 100644 index 85d0c23..0000000 --- a/src/Client/src/app/pages/store/admin/newitem/new.component.html +++ /dev/null @@ -1,50 +0,0 @@ -
-
-
-

Create New Item

- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- -
- -
- -
-
- -
-
- -
    -
  • {{ msg }}
  • -
-
- - -
-
- Image Preview -
-
-
-
\ No newline at end of file diff --git a/src/Client/src/app/pages/store/admin/newitem/new.component.ts b/src/Client/src/app/pages/store/admin/newitem/new.component.ts deleted file mode 100644 index 2171eb7..0000000 --- a/src/Client/src/app/pages/store/admin/newitem/new.component.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Component } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { FormsModule } from '@angular/forms'; -import { Router, ActivatedRoute } from '@angular/router'; -import { Title } from '@angular/platform-browser'; -import { CommonModule } from '@angular/common'; -import { Authentication } from '../../../../services/Authentication'; -import { Product } from 'app/models/Product'; - -@Component({ - selector: 'item-new', - templateUrl: './new.component.html', - imports: [ FormsModule, CommonModule ] -}) -export class NewItemComponent { - - readonly maxFileMB = 16; - - newItem: Product = new Product(); - errorMsgs: string[] = []; - - constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title, public auth: Authentication ) { - this.title.setTitle("New | ADMIN"); - - // If user is not logged in -> route home - if (!auth.isLoggedIn){ - router.navigate(["/"]); - } - - // If user is not Admin -> route home - if (auth.loggedInUser.siteData.role != "Admin"){ - router.navigate(["/"]); - } - }; - - sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - - selectedFiles: File[] = []; - imagePreviews: string[] = []; - onFileSelected(event: Event){ - const fileInput = event.target as HTMLInputElement; - this.imagePreviews = []; - this.selectedFiles = []; - - if (!fileInput.files?.length){ - return; - } - - for (let i=0; i this.maxFileMB * 1024 * 1024){ - this.errorMsgs.push("File exceeds max file size of 16MB"); - continue; - } - // No issues add file to the list - this.selectedFiles.push( file ); - - const reader = new FileReader(); - reader.onload= () => { - this.imagePreviews.push(reader.result as string); - } - reader.readAsDataURL(file); - } - } - - onSubmit(){ - - const formData = new FormData(); - - // Append non-file fields - formData.append("Name", this.newItem.name); - formData.append("Description", this.newItem.description); - formData.append("Cost", this.newItem.cost.toString()); - formData.append("Url", this.newItem.url); - - // Add image fileds - if (this.selectedFiles.length > 0){ - for(let i=0; i( "api/product/create", formData ).subscribe({ - next: async (data) => { - if (data == true){ - this.errorMsgs = ["Product Created Successfully"]; - await this.sleep(3000); - this.router.navigate(["store/catalog"]); - }else{ - this.errorMsgs = ["Error has ocurred"]; - } - }, - error: err => { - console.log("New Product Err: ", err); - } - }); - } -} \ No newline at end of file diff --git a/src/Client/src/app/pages/store/catalog/catalog.component.css b/src/Client/src/app/pages/store/catalog/catalog.component.css deleted file mode 100644 index 1081939..0000000 --- a/src/Client/src/app/pages/store/catalog/catalog.component.css +++ /dev/null @@ -1,145 +0,0 @@ -.gameCard { - position: relative; - background-color: var(--Mistox-Black); - float: left; - box-sizing: border-box; - margin: 0; - padding: 0; - width: 100%; - border-radius: 10px; - break-inside: avoid; - margin-bottom: 2rem; - border: solid 2px var(--Mistox-Background); - transition-duration: 1s; -} - -.gameCard :hover{ - border-color: var(--Mistox-Light); -} - -.gameCard-Name { - width: 100%; - text-align: left; - font-size: 25px; - padding: 5px 0 0 5px; - background-color: rgba(0,0,0,.1); -} - -.gameCard-Grid { - column-count: 4; - column-gap: 2rem; - padding-top: 20px; - width: calc(100% - 40px); - margin-left: 20px; -} - -@media (max-width: 1400px) { - .gameCard-Grid { - column-count: 3; - padding-top: 20px; - width: calc(100% - 40px); - margin-left: 20px; - } -} - -@media (max-width: 1100px) { - .gameCard-Grid { - column-count: 2; - padding-top: 20px; - width: calc(100% - 40px); - margin-left: 20px; - } -} - -@media (max-width: 900px) { - .gameCard-Grid { - column-count: 1; - padding-top: 20px; - width: calc(100% - 40px); - margin-left: 20px; - } -} - -.gameCard-Img { - width: 100%; - border-radius: 10px 10px 0 0; -} - -.gameCard-Next, -.gameCard-Prev { - background-color: transparent; - color: var(--Mistox-White); - padding: 16px; - margin-top: -22px; - font-size: 18px; - font-weight: bold; - border: none; - transition: background-color 0.6s ease; -} - - .gameCard-Next:hover, - .gameCard-Prev:hover { - background-color: rgba(0, 0, 0, 0.5); - } - -.gameCard-Prev { - position: absolute; - top: 50%; -} - -.gameCard-Next { - position: absolute; - top: 50%; - right: 0; -} - -.gameCard-Desc { - font-size: 13px; - margin: 5px; - color: var(--Mistox-Light); -} - -.gameCard-Price { - width: calc(50% - 10px); - float: left; - margin: 5px; - text-align: center; - margin-bottom: 10px; -} - -.gameCard-Button { - width: 40%; - margin: 5px 5%; - height: 38.4px; - color: var(--Mistox-Black); - background-color: var(--Mistox-Light); - font-size: 16px; - text-decoration: none; - text-transform: uppercase; - overflow: hidden; - transition: 0.5s; - letter-spacing: 2px; - border: 1px solid var(--Mistox-Light); - border-radius: 5px; -} - - .gameCard-Button :hover{ - background-color: var(--Mistox-Light); - color: var(--Mistox-White); - box-shadow: 4px 3px 6px var(--Mistox-Dark); - } - -.cartopen { - position: absolute; - background: var(--Mistox-Offset); - right: 10px; - top: 55px; - width: 400px; - border-radius: 5px; - backdrop-filter: blur(3px); - border: 1px solid var(--Mistox-Light); -} - -.cartclosed { - display: none; -} \ No newline at end of file diff --git a/src/Client/src/app/pages/store/catalog/catalog.component.html b/src/Client/src/app/pages/store/catalog/catalog.component.html deleted file mode 100644 index ee11ebb..0000000 --- a/src/Client/src/app/pages/store/catalog/catalog.component.html +++ /dev/null @@ -1,32 +0,0 @@ -
-
-
-
- - -
-
- -
-
-

{{ product.name }}

-
-

{{ line }}

-
-

${{ (product.cost/100).toFixed(2) }}

- -
- - -
-
-
- -
-
\ No newline at end of file diff --git a/src/Client/src/app/pages/store/catalog/catalog.component.ts b/src/Client/src/app/pages/store/catalog/catalog.component.ts deleted file mode 100644 index 4ee173c..0000000 --- a/src/Client/src/app/pages/store/catalog/catalog.component.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Component, NgZone } from '@angular/core'; -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { FormsModule, NgModel } from '@angular/forms'; -import { Router, ActivatedRoute, RouterModule } from '@angular/router'; -import { Title } from '@angular/platform-browser'; -import { CommonModule } from '@angular/common'; -import { Authentication } from '../../../services/Authentication'; -import { Product } from 'app/models/Product'; - -@Component({ - selector: 'store-catalog', - templateUrl: './catalog.component.html', - styleUrl: './catalog.component.css', - imports: [ FormsModule, CommonModule, RouterModule ] -}) -export class CatalogComponent { - - public Products: Product[] = []; - - constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title, public auth: Authentication ) { - this.title.setTitle("Store | Mistox"); - - // load each product - http.post("api/product/getall", null).subscribe( - response => { - this.Products = response; - - // Load each image - this.Products.forEach(item => { - item.curShowingIMG = 0; - item.images.forEach(img => { - http.get("api/productimage/get?ProductID=" + img.productID + "&ImageID=" + img.imageID, { responseType: 'blob' }).subscribe(blob => { - img.imageSrc = URL.createObjectURL(blob); - console.log(img.imageSrc); - }); - }); - }); - - } - ) - }; - - nextImg( prod: Product ){ - prod.curShowingIMG += 1; - if (prod.curShowingIMG == prod.images.length){ - prod.curShowingIMG = 0; - } - } - - prevImg( prod: Product ){ - prod.curShowingIMG -= 1; - if (prod.curShowingIMG == -1){ - prod.curShowingIMG = prod.images.length -1; - } - } - - DeleteItem( ProductID: number ) { - const body = new HttpParams() - .set("productID", ProductID); - const headers = new HttpHeaders({ - 'Content-Type': 'application/x-www-form-urlencoded', - }); - this.http.post( "api/product/delete", body, { headers } ).subscribe({ - next: data => { - if (data){ - window.location.reload(); - } - } - }) - } -} \ No newline at end of file diff --git a/src/Client/src/app/pages/store/payment/payment.component.css b/src/Client/src/app/pages/store/payment/payment.component.css deleted file mode 100644 index 30d2f6c..0000000 --- a/src/Client/src/app/pages/store/payment/payment.component.css +++ /dev/null @@ -1,24 +0,0 @@ -#payment-form { - max-width: 500px; - margin: 0 auto; -} - -.form-group { - margin-bottom: 20px; -} - -#card-element { - padding: 12px; - border: 1px solid #ccc; - border-radius: 4px; - background: #fff; -} - -#submit { - background-color: #5469d4; - color: white; - padding: 12px 20px; - border: none; - border-radius: 4px; - cursor: pointer; -} \ No newline at end of file diff --git a/src/Client/src/app/pages/store/payment/payment.component.html b/src/Client/src/app/pages/store/payment/payment.component.html deleted file mode 100644 index 52aca46..0000000 --- a/src/Client/src/app/pages/store/payment/payment.component.html +++ /dev/null @@ -1,8 +0,0 @@ -
-
- -
- -
- -
\ No newline at end of file diff --git a/src/Client/src/app/pages/store/payment/payment.component.ts b/src/Client/src/app/pages/store/payment/payment.component.ts deleted file mode 100644 index 8c285f2..0000000 --- a/src/Client/src/app/pages/store/payment/payment.component.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Component } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { FormsModule } from '@angular/forms'; -import { Router, ActivatedRoute, RouterModule } from '@angular/router'; -import { Title } from '@angular/platform-browser'; -import { CommonModule } from '@angular/common'; -import { Authentication } from '../../../services/Authentication'; -import { loadStripe, Stripe, StripeElements } from '@stripe/stripe-js'; -import { firstValueFrom } from 'rxjs'; - -@Component({ - selector: 'store-payment', - templateUrl: './payment.component.html', - styleUrl: './payment.component.css', - imports: [ FormsModule, CommonModule, RouterModule ] -}) -export class PaymentComponent { - - stripe: Stripe | null = null; - elements: StripeElements | null = null; - - async ngOnInit(){ - - let ApiKey = await firstValueFrom(this.http.get("/api/payment/publickey")); - - this.stripe = await loadStripe(ApiKey); - if (this.stripe){ - this.elements = this.stripe?.elements(); - } - } - - ngAfterViewInit(){ - if (this.elements){ - const cardStyle = { - base: { - color: '#32325d', - fontFamily: '"Helvetica Neue", Helvetica, sans-serif', - fontSize: '16px', - '::placeholder': { - color: '#aab7c4', - } - }, - invalid: { - color: '#fa755a', - } - } - const card = this.elements.create('card', { style: cardStyle }); - card.mount('#card-element'); - } - } - - constructor( private http: HttpClient, private router: Router, private route: ActivatedRoute, private title: Title, public auth: Authentication ) { - this.title.setTitle("Payment | Mistox"); - - http.post("api/product/getall", null).subscribe( - response => { - - } - ) - }; - -} \ No newline at end of file diff --git a/src/Client/src/app/services/Authentication.ts b/src/Client/src/app/services/Authentication.ts index ca3b9ae..138ccf7 100644 --- a/src/Client/src/app/services/Authentication.ts +++ b/src/Client/src/app/services/Authentication.ts @@ -24,22 +24,20 @@ export class Authentication{ let sub = this.http.post( "api/account/login", body, { headers } ); sub.subscribe({ next: data => { - if (data.error.length === 0){ - this._user.next(data); - this.setUserToStorage(data, StayLoggedIn == true ? SessionType.Forever : SessionType.Session); - } + this._user.next(data); + this.setUserToStorage(data, StayLoggedIn == true ? SessionType.Forever : SessionType.Session); }, error: err => { - console.log("HTTP Error Signing In: ", err); + console.log("HTTP Error Signing In: ", err.error); } }); return sub; } Logout(){ - this.http.post( "api/account/logout", {}, { responseType: 'json' } ).subscribe( ); this._user.next( new Account ); this.delUserFromStorage(); + return this.http.post( "api/account/logout", {}, { responseType: 'json' } ); } get isLoggedIn(): boolean { diff --git a/src/Server/Controllers/AuthenticationController.cs b/src/Server/Controllers/AuthenticationController.cs index 4a532da..994ddc1 100755 --- a/src/Server/Controllers/AuthenticationController.cs +++ b/src/Server/Controllers/AuthenticationController.cs @@ -5,7 +5,6 @@ using System.Security.Claims; using BoredCareers.Services; using BoredCareers.Services.DatabaseService; using BoredCareers.Entities; -using Microsoft.AspNetCore.Http.HttpResults; using System.Web.Http; namespace BoredCareers.Controllers { @@ -48,11 +47,11 @@ namespace BoredCareers.Controllers { IsPersistent = StayLoggedIn, // Is set from the StayLoggedIn } ); - return test; + return Ok(test); } else { test.CurrentPasswordAttempts += 1; await _databaseService.SetAccount(test); - return Ok(new Account() { ID = -1, UserName = "Wrong Password" }); + return NotFound("Wrong Password"); } } else { await SendVerify(test.UserName); @@ -62,7 +61,7 @@ namespace BoredCareers.Controllers { return NotFound("Account Not Found"); } catch (Exception ex) { Console.WriteLine("Login Error: " + ex.Message); - return NotFound(); + return NotFound("An internal server error has occured"); } } @@ -93,7 +92,7 @@ namespace BoredCareers.Controllers { } } catch (Exception ex) { Console.WriteLine("Register Error: " + ex.Message); - return NotFound(); + return NotFound("An internal server error has occured"); } } @@ -111,10 +110,10 @@ namespace BoredCareers.Controllers { return Ok(); } } - return NotFound(); + return NotFound("Not logged in"); } catch (Exception ex) { Console.WriteLine("ChangePassword Error: " + ex.Message); - return NotFound(); + return NotFound("An internal server error has occured"); } } @@ -129,10 +128,10 @@ namespace BoredCareers.Controllers { await _databaseService.SetAccount(user); return Ok(); } - return NotFound(); + return NotFound("Not logged in"); } catch (Exception ex) { Console.WriteLine("ToggleAccountLock Error: " + ex.Message); - return NotFound(); + return NotFound("An internal server error has occured"); } } @@ -143,10 +142,10 @@ namespace BoredCareers.Controllers { if (isLoggedIn()) { return Ok(await getLoggedInUser()); } - return NotFound(); + return NotFound("Not logged in"); } catch (Exception ex) { Console.WriteLine("Get Error: " + ex); - return NotFound(); + return NotFound("An internal server error has occured"); } } @@ -169,7 +168,7 @@ namespace BoredCareers.Controllers { if (_emailContext._SentEmails.ContainsKey(key)) { DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key); if (PreviousSentTime.AddMinutes(5) > DateTime.Now) { - return "Cannot sent another verify email until 5 minutes has elapsed "; + return NotFound("Cannot sent another verify email until 5 minutes has elapsed"); } else { _emailContext._SentEmails.Remove(key); @@ -187,11 +186,11 @@ namespace BoredCareers.Controllers { string result = _emailContext.Send(test.Email, EmailService.VerifyEmailSubject, EmailContents); _emailContext._SentEmails.Add(key, DateTime.Now); - return result; + return Ok(result); } - return "Account not found"; + return NotFound("Account not found"); } catch (Exception) { - return "The connection couldn't be established to the email server"; + return NotFound("An internal server error has occured"); } } @@ -205,12 +204,12 @@ namespace BoredCareers.Controllers { test.EmailToken = ""; test.EmailVerified = true; await _databaseService.SetAccount(test); - return true; + return Ok(true); } } - return false; + return NotFound("Account not found or token is invalid");; } catch { - return false; + return NotFound("An internal server error has occured"); } } @@ -223,7 +222,7 @@ namespace BoredCareers.Controllers { if (_emailContext._SentEmails.ContainsKey(key)) { DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key); if (PreviousSentTime.AddMinutes(5) > DateTime.Now) { - return "Cannot sent another reset requests until 5 minutes has elapsed"; + return NotFound("Cannot sent another reset requests until 5 minutes has elapsed"); } else { _emailContext._SentEmails.Remove(key); @@ -241,12 +240,12 @@ namespace BoredCareers.Controllers { string result = _emailContext.Send(test.Email, EmailService.VerifyEmailSubject, EmailContents); _emailContext._SentEmails.Add(key, DateTime.Now); - return result; + return Ok(result); } - return "Account Not Found"; + return NotFound("Account Not Found"); } catch (Exception e) { Console.WriteLine("EmailService Error: " + e.ToString()); - return "The connection couldn't be established to the email server"; + return NotFound("An internal server error has occured"); } } @@ -262,12 +261,12 @@ namespace BoredCareers.Controllers { test.EmailToken = ""; test.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword); await _databaseService.SetAccount(test); - return true; + return Ok(true); } } - return false; + return NotFound("Account not found or reset token is bad"); } catch { - return false; + return NotFound("An internal server error has occured"); } } @@ -282,10 +281,10 @@ namespace BoredCareers.Controllers { return Ok(); } } - return NotFound(); + return NotFound("User is not logged in"); } catch (Exception ex) { Console.WriteLine("Delete Error: " + ex.Message); - return NotFound(); + return NotFound("An internal server error has occured"); } } diff --git a/src/Server/Controllers/CompanyController.cs b/src/Server/Controllers/CompanyController.cs index cb644a2..2424d44 100644 --- a/src/Server/Controllers/CompanyController.cs +++ b/src/Server/Controllers/CompanyController.cs @@ -17,19 +17,30 @@ namespace BoredCareers.Controllers { if (company != null) { return Ok(company); } + return NotFound("Company doesn't exist"); } - return NotFound(); + return NotFound("Not logged in"); } [HttpPost] - public async Task SetCompany([FromBody] Company company) { + public async Task SetCompany([FromBody] Company company, [FromQuery] bool newCompany = false) { if (isLoggedIn()) { - if (await isLoggedInUserEmployeeOf(company.ID)) { - await _databaseService.SetCompany(company); - return Ok(); + if (newCompany) { + Company? test = await _databaseService.GetCompany(company.ID); + if (test == null) { + await _databaseService.SetCompany(company); + return Ok(); + } + return NotFound("The company already exists"); + } else { + if (await isLoggedInUserEmployeeOf(company.ID)) { + await _databaseService.SetCompany(company); + return Ok(); + } + return NotFound("You are not an employee of company"); } } - return NotFound(); + return NotFound("Not logged in"); } [HttpDelete] @@ -39,8 +50,9 @@ namespace BoredCareers.Controllers { await _databaseService.DeleteCompany(CompanyID); return Ok(); } + return NotFound("You are not an employee of company"); } - return NotFound(); + return NotFound("Not logged in"); } } diff --git a/src/Server/Controllers/JobListingController.cs b/src/Server/Controllers/JobListingController.cs index 495fb0b..a6c36a6 100644 --- a/src/Server/Controllers/JobListingController.cs +++ b/src/Server/Controllers/JobListingController.cs @@ -16,7 +16,7 @@ namespace BoredCareers.Controllers { if (jobListing != null) { return Ok(jobListing); } - return NotFound(); + return NotFound("Job listing not found"); } [HttpGet] @@ -30,9 +30,11 @@ namespace BoredCareers.Controllers { if (isLoggedIn()) { if (await isLoggedInUserEmployeeOf(JobListing.CompanyID)) { await _databaseService.SetJobListing(JobListing); + return Ok(); } + return NotFound("You are not an employee of company"); } - return NotFound(); + return NotFound("Not logged in"); } [HttpDelete] @@ -42,10 +44,13 @@ namespace BoredCareers.Controllers { if (jobListing != null) { if (await isLoggedInUserEmployeeOf(JobListingID)) { await _databaseService.DeleteJobListing(JobListingID); + return Ok(); } + return NotFound("You are not an employee of company"); } + return NotFound("Job listing doesn't exist already"); } - return NotFound(); + return NotFound("Not logged in"); } } diff --git a/src/Server/Controllers/ResumeController.cs b/src/Server/Controllers/ResumeController.cs index 65b9099..02ae46a 100644 --- a/src/Server/Controllers/ResumeController.cs +++ b/src/Server/Controllers/ResumeController.cs @@ -17,14 +17,15 @@ namespace BoredCareers.Controllers { if (resume != null) { return Ok(resume); } - }else{ + return NotFound("Unable to find resume"); + } else { if (isLoggedIn()) { int accountID = getLoggedInUserID(); Resume[] resumes = await _databaseService.GetResumes(accountID); return Ok(resumes); } + return NotFound("Not logged in"); } - return NotFound(); } [HttpPost] @@ -35,21 +36,23 @@ namespace BoredCareers.Controllers { await _databaseService.SetResume(resume); return Ok(); } + return NotFound("Resume doesn't exist or you are not the owner"); } - return NotFound(); + return NotFound("Not logged in"); } [HttpDelete] public async Task DeleteResume(int ResumeID) { - if (isLoggedIn()){ + if (isLoggedIn()) { int accountID = getLoggedInUserID(); Resume? resume = await _databaseService.GetResume(ResumeID); if (resume != null && resume.AccountID == accountID) { await _databaseService.DeleteResume(ResumeID); return Ok(); } + return NotFound("Resume doesn't exist or you are not the owner"); } - return NotFound(); + return NotFound("Not logged in"); } } diff --git a/src/Server/Services/DatabaseService/Account.cs b/src/Server/Services/DatabaseService/Account.cs index ae527da..09d5cf8 100755 --- a/src/Server/Services/DatabaseService/Account.cs +++ b/src/Server/Services/DatabaseService/Account.cs @@ -110,7 +110,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Account (ID,UserName,Email,EmailVerified,PasswordHash,FailedPasswordLock,PasswordAttempts,CurrentPasswordAttempts,Role,EmailToken,DataServer) VALUES - (@ID,@UserName,@Email,@EmailVerified,@PasswordHash,@FailedPasswordLock,@PasswordAttempts,@CurrentPasswordAttempts,@Role,@EmailToken,@DataServer); + (@ID,@UserName,@Email,@EmailVerified,@PasswordHash,@FailedPasswordLock,@PasswordAttempts,@CurrentPasswordAttempts,@Role,@EmailToken,@DataServer) ON DUPLICATE KEY UPDATE UserName = @UserName, Email = @Email, @@ -120,7 +120,7 @@ namespace BoredCareers.Services.DatabaseService { PasswordAttempts = @PasswordAttempts, CurrentPasswordAttempts = @CurrentPasswordAttempts, Role = @Role, - EmailToken = @EmailToken; + EmailToken = @EmailToken, DataServer = @DataServer; "; diff --git a/src/Server/Services/DatabaseService/Company.cs b/src/Server/Services/DatabaseService/Company.cs index 2eafd16..26aaa5f 100644 --- a/src/Server/Services/DatabaseService/Company.cs +++ b/src/Server/Services/DatabaseService/Company.cs @@ -60,10 +60,10 @@ namespace BoredCareers.Services.DatabaseService { connection.Open(); string command = @" - INSERT INTO Account + INSERT INTO Company (ID,Name,Email,EmailVerified,WebsiteURL,LogoURL,Phone,PostalCode,Country,StateOrRegion,City,Description) VALUES - (@ID,@Name,@Email,@EmailVerified,@WebsiteURL,@LogoURL,@Phone,@PostalCode,@Country,@StateOrRegion,@City,@Description); + (@ID,@Name,@Email,@EmailVerified,@WebsiteURL,@LogoURL,@Phone,@PostalCode,@Country,@StateOrRegion,@City,@Description) ON DUPLICATE KEY UPDATE Name = @Name, Email = @Email, @@ -73,7 +73,7 @@ namespace BoredCareers.Services.DatabaseService { Phone = @Phone, PostalCode = @PostalCode, Country = @Country, - StateOrRegion = @StateOrRegion; + StateOrRegion = @StateOrRegion, City = @City, Description = @Description; "; diff --git a/src/Server/Services/DatabaseService/Employee.cs b/src/Server/Services/DatabaseService/Employee.cs index e317e89..f31261d 100644 --- a/src/Server/Services/DatabaseService/Employee.cs +++ b/src/Server/Services/DatabaseService/Employee.cs @@ -45,7 +45,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Employee (ID,AccountID,CompanyID) VALUES - (@ID,@AccountID,@CompanyID); + (@ID,@AccountID,@CompanyID) ON DUPLICATE KEY UPDATE AccountID = @AccountID, CompanyID = @CompanyID; diff --git a/src/Server/Services/DatabaseService/JobListing.cs b/src/Server/Services/DatabaseService/JobListing.cs index 384fa84..1b99c8b 100644 --- a/src/Server/Services/DatabaseService/JobListing.cs +++ b/src/Server/Services/DatabaseService/JobListing.cs @@ -127,7 +127,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO JobListing (ID,CompanyID,Title,PostalCode,Country,StateOrRegion,City,SalaryMin,SalaryMax,JobType,Remote,Description,CreatedTime,ModifiedTime,IsDeleted) VALUES - (@ID,@CompanyID,@Title,@PostalCode,@Country,@StateOrRegion,@City,@SalaryMin,@SalaryMax,@JobType,@Remote,@Description,@CreatedTime,@ModifiedTime,@IsDeleted); + (@ID,@CompanyID,@Title,@PostalCode,@Country,@StateOrRegion,@City,@SalaryMin,@SalaryMax,@JobType,@Remote,@Description,@CreatedTime,@ModifiedTime,@IsDeleted) ON DUPLICATE KEY UPDATE CompanyID = @CompanyID, Title = @Title, diff --git a/src/Server/Services/DatabaseService/ResumeParts/SetResumeParts.cs b/src/Server/Services/DatabaseService/ResumeParts/SetResumeParts.cs index 089f385..55ff142 100644 --- a/src/Server/Services/DatabaseService/ResumeParts/SetResumeParts.cs +++ b/src/Server/Services/DatabaseService/ResumeParts/SetResumeParts.cs @@ -9,7 +9,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,AccountID,Name,Field,Email,PhoneNumber,PostalCode,Country,StateOrRegion,City,IsActive) VALUES - (@ID,@AccountID,@Name,@Field,@Email,@PhoneNumber,@PostalCode,@Country,@StateOrRegion,@City,@IsActive); + (@ID,@AccountID,@Name,@Field,@Email,@PhoneNumber,@PostalCode,@Country,@StateOrRegion,@City,@IsActive) ON DUPLICATE KEY UPDATE AccountID = @AccountID, Name = @Name, @@ -45,7 +45,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,ResumeExperienceID,JobFunction) VALUES - (@ID,@ResumeID,@ResumeExperienceID,@JobFunction); + (@ID,@ResumeID,@ResumeExperienceID,@JobFunction) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, ResumeExperienceID = @ResumeExperienceID, @@ -68,7 +68,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,JobTitle,Company,PostalCode,Country,StateOrRegion,City,DateStarted,StillEmployed,DateEnded) VALUES - (@ID,@ResumeID,@JobTitle,@Company,@PostalCode,@Country,@StateOrRegion,@City,@DateStarted,@StillEmployed,@DateEnded); + (@ID,@ResumeID,@JobTitle,@Company,@PostalCode,@Country,@StateOrRegion,@City,@DateStarted,@StillEmployed,@DateEnded) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, JobTitle = @JobTitle, @@ -102,7 +102,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,ResumeMilitaryID,Achievement) VALUES - (@ID,@ResumeID,@ResumeMilitaryID,@Achievement); + (@ID,@ResumeID,@ResumeMilitaryID,@Achievement) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, ResumeMilitaryID = @ResumeMilitaryID, @@ -126,7 +126,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,Country,Rank,DateStarted,StillServing,DateEnded) VALUES - (@ID,@ResumeID,@Country,@Rank,@DateStarted,@StillServing,@DateEnded); + (@ID,@ResumeID,@Country,@Rank,@DateStarted,@StillServing,@DateEnded) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, Country = @Country, @@ -154,7 +154,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,DegreeType,DegreeField,School,PostalCode,Country,StateOrRegion,City,DateStarted,StillStudying,DateEnded) VALUES - (@ID,@ResumeID,@DegreeType,@DegreeField,@School,@PostalCode,@Country,@StateOrRegion,@City,@DateStarted,@StillStudying,@DateEnded); + (@ID,@ResumeID,@DegreeType,@DegreeField,@School,@PostalCode,@Country,@StateOrRegion,@City,@DateStarted,@StillStudying,@DateEnded) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, DegreeType = @DegreeType, @@ -193,7 +193,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,Name,Description) VALUES - (@ID,@ResumeID,@Name,@Description); + (@ID,@ResumeID,@Name,@Description) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, Name = @Name, @@ -216,7 +216,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,Language,Proficiency) VALUES - (@ID,@ResumeID,@Language,@Proficiency); + (@ID,@ResumeID,@Language,@Proficiency) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, Language = @Language, @@ -239,7 +239,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,Name,VerificationURL,Description) VALUES - (@ID,@ResumeID,@Name,@VerificationURL,@Description); + (@ID,@ResumeID,@Name,@VerificationURL,@Description) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, Name = @DegreeNameType, @@ -264,7 +264,7 @@ namespace BoredCareers.Services.DatabaseService { INSERT INTO Resume (ID,ResumeID,Name,URL,Description) VALUES - (@ID,@ResumeID,@Name,@URL,@Description); + (@ID,@ResumeID,@Name,@URL,@Description) ON DUPLICATE KEY UPDATE ResumeID = @ResumeID, Name = @Name,