diff --git a/package.json b/package.json index 2bd9de1..3874e23 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pay-point", - "version": "0.0.21", + "version": "0.0.3", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index ee4820a..1c02099 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -3,6 +3,8 @@ import {AgendaComponent} from './pages/agenda/agenda.component'; import {LoginComponent} from './pages/login/login.component'; import {HomeComponent} from './pages/home/home.component'; import {KlantenComponent} from './pages/klanten/klanten.component'; +import {AgendaInviteComponent} from './pages/agenda-invite/agenda-invite.component'; +import {AgendaDelenComponent} from './pages/agenda-delen/agenda-delen.component'; export const routes: Routes = [ {path: '', redirectTo: 'login', pathMatch: 'full'}, @@ -19,6 +21,14 @@ export const routes: Routes = [ path: 'klanten', component: KlantenComponent, }, + { + path: 'agenda-invite', + component: AgendaInviteComponent + }, + { + path: 'agenda-delen', + component: AgendaDelenComponent + } // { // path: 'dashboard', // component: DashboardComponent, diff --git a/src/app/components/dropdown-content/dropdown-content.component.html b/src/app/components/dropdown-content/dropdown-content.component.html new file mode 100644 index 0000000..9f8cb10 --- /dev/null +++ b/src/app/components/dropdown-content/dropdown-content.component.html @@ -0,0 +1,34 @@ + diff --git a/src/app/components/dropdown-content/dropdown-content.component.scss b/src/app/components/dropdown-content/dropdown-content.component.scss new file mode 100644 index 0000000..78e8fce --- /dev/null +++ b/src/app/components/dropdown-content/dropdown-content.component.scss @@ -0,0 +1,35 @@ +.dropdown-content { + border-radius: 12px; + background-color: white; + min-width: 220px; +} + +.dropdown-section-title { + font-size: 0.75rem; + font-weight: 600; + color: #6b7280; + text-transform: uppercase; + margin-bottom: 0.5rem; + margin-top: 1rem; + padding-left: 0.25rem; +} + +.dropdown-item { + display: flex; + align-items: center; + padding: 0.5rem 0.75rem; + border-radius: 8px; + transition: background-color 0.2s ease; + font-size: 0.95rem; + gap: 0.5rem; + white-space: nowrap; + + &:hover { + background-color: #f3f4f6; + } + + &:focus { + outline: none; + background-color: #e5e7eb; + } +} diff --git a/src/app/components/dropdown-content/dropdown-content.component.ts b/src/app/components/dropdown-content/dropdown-content.component.ts new file mode 100644 index 0000000..fb5c57a --- /dev/null +++ b/src/app/components/dropdown-content/dropdown-content.component.ts @@ -0,0 +1,37 @@ +import {Component, EventEmitter, Output} from '@angular/core'; +import {TuiDataListComponent, TuiIcon, TuiOption} from '@taiga-ui/core'; +import {Router} from '@angular/router'; + +@Component({ + selector: 'dropdown-content', + imports: [ + TuiDataListComponent, + TuiOption, + TuiIcon + ], + templateUrl: './dropdown-content.component.html', + styleUrl: './dropdown-content.component.scss' +}) +export class DropdownContentComponent { + + constructor(private router: Router) { + } + + currentView: 'day' | 'week' | 'year' = 'day' + @Output() close = new EventEmitter() + + shareAgenda() { + this.close.emit()/* open modal etc */ + this.router.navigate(['/home/agenda-delen']) + } + + switchAgenda() { + this.close.emit()/* toggle agenda */ + } + + setView(view: 'day' | 'week' | 'year') { + this.close.emit() + this.currentView = view; + } + +} diff --git a/src/app/components/new-item/new-item.component.html b/src/app/components/new-item/new-item.component.html index b7527c2..6ca0aed 100644 --- a/src/app/components/new-item/new-item.component.html +++ b/src/app/components/new-item/new-item.component.html @@ -118,7 +118,7 @@ size="m" tuiButton type="button" (click)="registerAppointment()" - id="afspraakMaken" + id="afspraakPlannen" [tuiAppearanceState]="formIsValid()"> Afspraak maken diff --git a/src/app/interceptors/auth-interceptor.ts b/src/app/interceptors/auth-interceptor.ts index e3dbf1e..f4f5ca3 100644 --- a/src/app/interceptors/auth-interceptor.ts +++ b/src/app/interceptors/auth-interceptor.ts @@ -1,16 +1,15 @@ import {HttpInterceptorFn} from '@angular/common/http'; import {inject} from '@angular/core'; -import {AuthService} from '../services/auth.service'; +import {UserService} from '../services/user.service'; const excludedUrls = ['/auth/login']; export const AuthInterceptor: HttpInterceptorFn = (req, next) => { - const authService = inject(AuthService); - const token = authService.getToken(); - + const userService = inject(UserService); if (excludedUrls.some(url => req.url.includes(url))) { return next(req); } + const token: string | null = userService.userValue.token ?? null; if (token) { const cloned = req.clone({ diff --git a/src/app/models/app-user-dto.ts b/src/app/models/app-user-dto.ts new file mode 100644 index 0000000..f78ddae --- /dev/null +++ b/src/app/models/app-user-dto.ts @@ -0,0 +1,29 @@ +export class AppUserDto { + id: number; + username: string; + email: string; + firstName: string; + lastName: string; + role: string; + token: string; + companies: UserCompanyDTO[]; +} + +export interface CompanyDTO { + id: number; + name: string; + email: string; + address: string; + postalCode: string; + city: string; + imgHref: string; +} + +export type AccessLevel = 'READ_ONLY' | 'USER'; + +export interface UserCompanyDTO { + id: string; + accessLevel: AccessLevel; + company: CompanyDTO; +} + diff --git a/src/app/models/invite-entity.ts b/src/app/models/invite-entity.ts new file mode 100644 index 0000000..8b273a7 --- /dev/null +++ b/src/app/models/invite-entity.ts @@ -0,0 +1,9 @@ +export class InviteEntity { + id: string; + company_id: number; + email: string; + token: string; + expiresAt: string; // ISO date string + used: boolean; + createdAt: string; // ISO date string +} diff --git a/src/app/models/user-dto.ts b/src/app/models/user-dto.ts deleted file mode 100644 index c85512c..0000000 --- a/src/app/models/user-dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class UserDto { - username: string - fullName: string - email: string - token: string - - constructor() { - } -} diff --git a/src/app/pages/agenda-delen/agenda-delen.component.html b/src/app/pages/agenda-delen/agenda-delen.component.html new file mode 100644 index 0000000..27074f6 --- /dev/null +++ b/src/app/pages/agenda-delen/agenda-delen.component.html @@ -0,0 +1,30 @@ +
+

Deel je agenda

+ +

Kies het bedrijf waarvoor je de agenda wilt delen:

+ + + + +
diff --git a/src/app/pages/agenda-delen/agenda-delen.component.scss b/src/app/pages/agenda-delen/agenda-delen.component.scss new file mode 100644 index 0000000..3d9c891 --- /dev/null +++ b/src/app/pages/agenda-delen/agenda-delen.component.scss @@ -0,0 +1,139 @@ +@keyframes fadeInOut { + 0% { + opacity: 0; + transform: translateY(5px); + } + 10% { + opacity: 1; + transform: translateY(0); + } + 90% { + opacity: 1; + transform: translateY(0); + } + 100% { + opacity: 0; + transform: translateY(-5px); + } +} + +.share-wrapper { + max-width: 500px; + margin: 2rem auto; + padding: 2rem; + background: #fff; + border-radius: 1rem; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + font-family: 'Segoe UI', sans-serif; + + h1 { + font-size: 1.8rem; + margin-bottom: 1rem; + } + + p { + margin-bottom: 0.5rem; + font-weight: 500; + } + + .custom-select { + width: 100%; + padding: 0.75rem 1rem; + border: 1px solid #ccc; + border-radius: 0.5rem; + font-size: 1rem; + appearance: none; + background-color: #f9f9f9; + background-image: url('data:image/svg+xml;utf8,'); + background-repeat: no-repeat; + background-position: right 1rem center; + background-size: 1rem; + cursor: pointer; + transition: border-color 0.3s, box-shadow 0.3s; + + &:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25); + } + } + + .link-section { + margin-top: 2rem; + + .label { + font-weight: 600; + margin-bottom: 0.5rem; + } + + .link-box { + display: flex; + align-items: center; + gap: 0.5rem; + + input[type="text"], input[type="email"] { + flex: 1; + padding: 0.6rem 1rem; + border: 1px solid #ccc; + border-radius: 0.5rem; + font-size: 0.95rem; + background-color: #f5f5f5; + transition: box-shadow 0.3s; + + &:focus { + outline: none; + box-shadow: 0 0 0 3px rgba(0, 150, 136, 0.25); + } + } + + .copy-button { + background: #eee; + border: none; + border-radius: 0.5rem; + padding: 0.5rem 0.75rem; + font-size: 1.2rem; + cursor: pointer; + transition: background 0.2s, transform 0.1s; + + &:hover { + background: #ddd; + } + + &:active { + transform: scale(0.95); + } + } + } + + .copied-msg { + margin-top: 0.5rem; + color: #28a745; + font-weight: 600; + animation: fadeInOut 2.5s ease-in-out forwards; + } + } +} + +a{ + text-decoration: none; + color: white; +} + +.share-wrapper{ + animation: fadeIn 0.4s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(15px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.share-media button { + margin-right: 8px; +} diff --git a/src/app/pages/agenda-delen/agenda-delen.component.ts b/src/app/pages/agenda-delen/agenda-delen.component.ts new file mode 100644 index 0000000..0874e17 --- /dev/null +++ b/src/app/pages/agenda-delen/agenda-delen.component.ts @@ -0,0 +1,101 @@ +import {Component, Inject, OnInit} from '@angular/core'; +import {TuiSelectModule} from '@taiga-ui/legacy'; +import {FormControl, FormsModule, ReactiveFormsModule, Validators} from '@angular/forms'; +import {TuiAlertService, TuiButton} from '@taiga-ui/core'; +import {NgForOf, NgIf} from '@angular/common'; +import {Company} from '../../models/company'; +import {CompanyService} from '../../services/company.service'; +import {AgendaService} from '../../services/agenda.service'; +import {Router} from '@angular/router'; +import {InviteEntity} from '../../models/invite-entity'; +import {UserService} from '../../services/user.service'; +import {CompanyDTO} from '../../models/app-user-dto'; + +@Component({ + selector: 'app-agenda-delen', + imports: [ + TuiSelectModule, + FormsModule, + NgIf, + FormsModule, + NgForOf, + ReactiveFormsModule, + TuiButton, + ], + templateUrl: './agenda-delen.component.html', + styleUrl: './agenda-delen.component.scss' +}) +export class AgendaDelenComponent implements OnInit { + companies: CompanyDTO[]; + selectedCompany: CompanyDTO | null = null; + companyForm: FormControl; + email: FormControl; + invite: InviteEntity; + + constructor(@Inject(TuiAlertService) private readonly alerts: TuiAlertService, private companyService: CompanyService, private agendaService: AgendaService, private router: Router, private userService: UserService) { + } + + ngOnInit(): void { + this.companyForm = new FormControl(''); + this.email = new FormControl('', [ + Validators.pattern(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/), + Validators.required]); + this.companyForm.valueChanges.subscribe( + companyToSelect => { + console.log(companyToSelect); + this.selectCompany(companyToSelect); + + } + ) + this.email.valueChanges.subscribe( + () => { + if (this.email.valid) { + this.createInvite() + } + } + ) + this.companies = this.userService.userValue.companies.map(a => a.company) + this.selectedCompany = this.companies[0] + this.companyForm.setValue(this.selectedCompany.id); + } + + get shareLink(): string | null { + if (!this.invite) return null; + return `${window.location.origin}/#/home/agenda-invite?token=${this.invite.token}`; + } + + copyLink(): void { + if (this.shareLink) { + navigator.clipboard.writeText(this.shareLink); + this.alerts.open('Link gekopieerd naar klembord.').subscribe(); + } + } + + selectCompany(companyId: number): void { + console.log(companyId); + this.selectedCompany = this.companies.find(company => + company.id == companyId + ); + console.log(this.selectedCompany); + } + + sendInvite(): void { + this.agendaService.sendInvite(this.shareLink, this.email.value).subscribe( + () => { + console.log('Successfully sent invite') + this.router.navigate(['/home/agenda']); + this.alerts.open(`Email is verstuurd naar: ${this.email.value}`).subscribe(); + } + ) + } + + createInvite(): void { + this.agendaService.createInvite(this.selectedCompany.id, this.email.value).subscribe( + response => { + this.invite = response + } + ) + } + + protected readonly encodeURIComponent = encodeURIComponent; +} diff --git a/src/app/pages/agenda-invite/agenda-invite.component.html b/src/app/pages/agenda-invite/agenda-invite.component.html new file mode 100644 index 0000000..ab29bfb --- /dev/null +++ b/src/app/pages/agenda-invite/agenda-invite.component.html @@ -0,0 +1,22 @@ +
+

Agenda-uitnodiging ontvangen

+ +

+ Je bent uitgenodigd om toegang te krijgen tot de agenda: +
+ {{ company.name }} +

+ +

+ Je bent uitgenodigd om toegang te krijgen tot een agenda. Wil je deze uitnodiging accepteren? +

+ + +
diff --git a/src/app/pages/agenda-invite/agenda-invite.component.scss b/src/app/pages/agenda-invite/agenda-invite.component.scss new file mode 100644 index 0000000..f91f949 --- /dev/null +++ b/src/app/pages/agenda-invite/agenda-invite.component.scss @@ -0,0 +1,54 @@ +.invite-wrapper { + max-width: 500px; + margin: 4rem auto; + padding: 2rem; + border-radius: 1rem; + background-color: #ffffff; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.05); + text-align: center; + font-family: 'Inter', sans-serif; + + h1 { + font-size: 1.5rem; + margin-bottom: 1rem; + font-weight: 600; + color: #1f2937; // donkergrijs + } + + p { + font-size: 1rem; + color: #4b5563; // medium grijs + margin-bottom: 2rem; + + strong { + color: #111827; // bijna zwart + } + } + + button { + font-size: 1rem; + padding: 0.75rem 1.5rem; + border-radius: 0.75rem; + font-weight: 500; + transition: background-color 0.2s ease; + + &:hover { + background-color: #5b6dfb; // iets donkerder blauw + } + } +} + +.invite-wrapper { + animation: fadeIn 0.4s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(15px); + } + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/src/app/pages/agenda-invite/agenda-invite.component.ts b/src/app/pages/agenda-invite/agenda-invite.component.ts new file mode 100644 index 0000000..8f3a09b --- /dev/null +++ b/src/app/pages/agenda-invite/agenda-invite.component.ts @@ -0,0 +1,51 @@ +import {Component, OnInit} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; +import {TuiAlertService, TuiButton} from '@taiga-ui/core'; +import {NgIf} from '@angular/common'; +import {CompanyService} from '../../services/company.service'; +import {Company} from '../../models/company'; +import {AgendaService} from '../../services/agenda.service'; +import {InviteEntity} from '../../models/invite-entity'; +import {CompanyDTO} from '../../models/app-user-dto'; +import {UserService} from '../../services/user.service'; + +@Component({ + selector: 'app-agenda-invite', + imports: [ + TuiButton, + NgIf + ], + templateUrl: './agenda-invite.component.html', + styleUrl: './agenda-invite.component.scss' +}) +export class AgendaInviteComponent implements OnInit { + token: string = ''; + agendaName: string = '...'; + company: CompanyDTO; + inviteEntity: InviteEntity; + + constructor(private route: ActivatedRoute, private router: Router, private companyService: CompanyService, private agendaService: AgendaService, private userService: UserService, private alerts: TuiAlertService) { + } + + ngOnInit(): void { + this.token = this.route.snapshot.queryParamMap.get('token'); + this.agendaService.verifyInvite(this.token).subscribe({ + next: (invite: InviteEntity) => { + this.inviteEntity = invite + this.companyService.getCompany(invite.company_id).subscribe(companyResponse => { + this.company = companyResponse; + }) + }, + error: (error) => console.log(error), + }); + } + + acceptInvite(): void { + this.companyService.linkCompany(this.userService.userValue.id, this.inviteEntity.token).subscribe( + () => { + this.alerts.open(`Agenda ${this.company.name} is toegevoegd.`).subscribe(); + this.router.navigate(['home/agenda']); + } + ) + } +} diff --git a/src/app/pages/agenda/agenda.component.html b/src/app/pages/agenda/agenda.component.html index 556d971..577b254 100644 --- a/src/app/pages/agenda/agenda.component.html +++ b/src/app/pages/agenda/agenda.component.html @@ -75,7 +75,9 @@ - +
@@ -115,3 +117,5 @@ + + diff --git a/src/app/pages/agenda/agenda.component.scss b/src/app/pages/agenda/agenda.component.scss index 399a180..91bc3fc 100644 --- a/src/app/pages/agenda/agenda.component.scss +++ b/src/app/pages/agenda/agenda.component.scss @@ -139,3 +139,23 @@ strong, p { .date:hover { text-decoration: underline; } + +.dropdown{ + padding-left: 12px; + padding-right: 12px; +} + +.calendar { + animation: fadeIn 0.4s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(-15px); + } + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/src/app/pages/agenda/agenda.component.ts b/src/app/pages/agenda/agenda.component.ts index 3f1430f..17065a2 100644 --- a/src/app/pages/agenda/agenda.component.ts +++ b/src/app/pages/agenda/agenda.component.ts @@ -18,13 +18,14 @@ import {DateFormatter} from '../../utils/date-formatter'; import {WeekDay} from '../../models/week-day'; import {NewItemComponent} from '../../components/new-item/new-item.component'; import {timeAfterStartValidator} from '../../models/validators/time-after-start-validator'; +import {DropdownContentComponent} from '../../components/dropdown-content/dropdown-content.component'; @Component({ selector: 'app-agenda', imports: [NgFor, TuiButton, CommonModule, NgIf, ModalComponent, ReactiveFormsModule, TuiInputTimeModule, TuiTextfieldControllerModule, - TuiInputModule, TuiTextareaModule, TuiInputDateModule, TuiIcon, DetailsComponent, TuiCalendar, NewItemComponent], + TuiInputModule, TuiTextareaModule, TuiInputDateModule, TuiIcon, DetailsComponent, TuiCalendar, NewItemComponent, DropdownContentComponent], templateUrl: './agenda.component.html', providers: [tuiDateFormatProvider({separator: '-'}), AppointmentService], styleUrl: './agenda.component.scss' diff --git a/src/app/pages/home/home.component.scss b/src/app/pages/home/home.component.scss index 2ca785c..38e8645 100644 --- a/src/app/pages/home/home.component.scss +++ b/src/app/pages/home/home.component.scss @@ -48,9 +48,7 @@ tui-avatar { font-size: 0.8125rem; line-height: 1.25rem; padding: 0.25rem 0.75rem; - margin-left: 4px; - margin-right: 20px; - margin-bottom: 8px; + margin: 20px 20px 8px 4px; min-width: 200px; } diff --git a/src/app/pages/home/home.component.ts b/src/app/pages/home/home.component.ts index 1d74e02..4a6e352 100644 --- a/src/app/pages/home/home.component.ts +++ b/src/app/pages/home/home.component.ts @@ -3,13 +3,13 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {Router, RouterLink, RouterLinkActive, RouterModule} from '@angular/router'; import {TuiAvatar, TuiChevron,} from '@taiga-ui/kit'; import {AuthService} from '../../services/auth.service'; -import {User} from '../../models/user'; import {TuiButton, TuiDropdown} from '@taiga-ui/core'; import {TuiActiveZone, TuiObscured} from '@taiga-ui/cdk'; import {environment} from '../../../environments/environment'; import {Company} from '../../models/company'; -import {CompanyService} from '../../services/company.service'; import {TuiSelectModule} from '@taiga-ui/legacy'; +import {UserService} from '../../services/user.service'; +import {AppUserDto, CompanyDTO} from '../../models/app-user-dto'; @Component({ selector: 'app-home', @@ -18,12 +18,13 @@ import {TuiSelectModule} from '@taiga-ui/legacy'; styleUrl: './home.component.scss' }) export class HomeComponent implements OnInit { - user: User + user: AppUserDto; fullName: string - companies: Company[] + companies: CompanyDTO[]; + currentCompany: CompanyDTO; getInitials(): string { - this.user = this.authService.getUserInfo(); + this.user = this.userService.userValue this.fullName = this.user.firstName + ' ' + this.user.lastName; return this.fullName.split(' ').map((n) => n[0]).join('').substring(0, 2); } @@ -44,29 +45,23 @@ export class HomeComponent implements OnInit { this.open = active && this.open; } - constructor(private authService: AuthService, private router: Router, private companyService: CompanyService) { + constructor(private authService: AuthService, private router: Router, private userService: UserService) { } ngOnInit(): void { - if (!this.authService.isAuthenticated()) { + if (!this.userService.userValue) { this.router.navigate(['login']); } else { - this.companyService.getCompanies().subscribe( - response => { - this.companies = response - this.authService.setCurrentCompany(response[0]) - console.log(this.companies) - } - ) + this.companies = this.userService.userValue.companies.map(a => a.company) + this.currentCompany = this.companies[0]; } } logout() { - this.authService.logout(); + this.userService.clearUser(); this.router.navigate(['login']); } protected readonly environment = environment; - currentCompany: Company; } diff --git a/src/app/pages/login/login.component.ts b/src/app/pages/login/login.component.ts index 7bc6190..f387d8a 100644 --- a/src/app/pages/login/login.component.ts +++ b/src/app/pages/login/login.component.ts @@ -4,10 +4,11 @@ import {Router} from '@angular/router'; import {TuiAppearance, TuiButton, TuiError, TuiTextfield,} from '@taiga-ui/core'; import {TuiCardLarge, TuiForm, TuiHeader} from '@taiga-ui/layout'; import {AuthService} from '../../services/auth.service'; -import {UserDto} from '../../models/user-dto'; +import {AppUserDto} from '../../models/app-user-dto'; import {HttpErrorResponse} from '@angular/common/http'; import {TuiValidationError} from '@taiga-ui/cdk'; import {environment} from '../../../environments/environment'; +import {UserService} from '../../services/user.service'; @Component({ selector: 'app-login', @@ -35,7 +36,7 @@ export class LoginComponent { return this.enabled ? this.error : null; } - constructor(private router: Router, private authService: AuthService) { + constructor(private router: Router, private authService: AuthService, private userService: UserService) { this.form = new FormGroup({ username: new FormControl('', Validators.required), password: new FormControl('', Validators.required) @@ -44,9 +45,10 @@ export class LoginComponent { login() { + console.log('IM LOGGING IN') this.authService.login(this.form.get('username').value, this.form.get('password').value).subscribe({ - next: (user: UserDto) => { - localStorage.setItem('token', user.token); + next: (user: AppUserDto) => { + this.userService.setUser(user); this.router.navigate(['/home/agenda']); }, error: (err: HttpErrorResponse) => { diff --git a/src/app/services/agenda.service.ts b/src/app/services/agenda.service.ts new file mode 100644 index 0000000..40f48c1 --- /dev/null +++ b/src/app/services/agenda.service.ts @@ -0,0 +1,32 @@ +import {Injectable} from '@angular/core'; +import {environment} from '../../environments/environment'; +import {HttpClient} from '@angular/common/http'; +import {Observable} from 'rxjs'; +import {InviteEntity} from '../models/invite-entity'; + +@Injectable({ + providedIn: 'root' +}) +export class AgendaService { + + baseApi = `${environment.baseApi}/agenda`; + + constructor(private http: HttpClient) { + } + + sendInvite(url: string, email: string): Observable { + return this.http.post(`${this.baseApi}/${email}`, {url}); + } + + createInvite(companyId: number, email: string): Observable { + return this.http.post(`${this.baseApi}/createinvite`, {companyId: companyId, email: email}); + } + + verifyInvite(token: string) { + return this.http.get(this.baseApi + `/verify?token=${token}`, {}) + } + + acceptInvite(user: number, company: number): Observable { + return this.http.post(this.baseApi + `/link?user=${user}&company=${company}`, {}) + } +} diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index f76a255..2a3c166 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -18,6 +18,7 @@ export class AuthService { } login(username: string, password: string): Observable { + console.log(username + ' is logging in'); return this.http.post(this.baseApi, {username, password}); } diff --git a/src/app/services/company.service.ts b/src/app/services/company.service.ts index 30f6603..f08df7b 100644 --- a/src/app/services/company.service.ts +++ b/src/app/services/company.service.ts @@ -3,6 +3,7 @@ import {HttpClient} from '@angular/common/http'; import {Observable} from 'rxjs'; import {environment} from '../../environments/environment'; import {Company} from '../models/company'; +import {CompanyDTO} from '../models/app-user-dto'; @Injectable({ providedIn: 'root', @@ -16,4 +17,13 @@ export class CompanyService { getCompanies(): Observable { return this.http.get(`${this.baseApi}`); } + + getCompany(id: number): Observable { + console.log(id) + return this.http.get(`${this.baseApi}/${id}`); + } + + linkCompany(user: number, token: string): Observable { + return this.http.post(this.baseApi + `/link?user=${user}&token=${token}`, {}) + } } diff --git a/src/app/services/user.service.ts b/src/app/services/user.service.ts new file mode 100644 index 0000000..8ed928c --- /dev/null +++ b/src/app/services/user.service.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import {AppUserDto} from '../models/app-user-dto'; + +@Injectable({ + providedIn: 'root' +}) +export class UserService { + private userSubject = new BehaviorSubject(null); + + get user$(): Observable { + return this.userSubject.asObservable(); + } + + get userValue(): AppUserDto | null { + return this.userSubject.value; + } + + constructor() { + const storedUser = localStorage.getItem('appUser'); + if (storedUser) { + this.userSubject.next(JSON.parse(storedUser)); + } + } + + setUser(user: AppUserDto): void { + localStorage.setItem('appUser', JSON.stringify(user)); + this.userSubject.next(user); + } + + clearUser(): void { + localStorage.removeItem('appUser'); + this.userSubject.next(null); + } + +} +