diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 7068cc2..5333a8b 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,10 +1,16 @@ import { Routes } from '@angular/router'; +import { IsLoggedInCanActivate } from './services/auth.service'; export const routes: Routes = [ { path: 'auth', loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule) }, + { + path: 'chat', + loadChildren: () => import('./chat/chat.module').then(m => m.ChatModule), + canActivate: [IsLoggedInCanActivate] + }, { path: '', redirectTo: 'auth', pathMatch: 'full' }, - { path: '**', redirectTo: '/', pathMatch: 'full' } + { path: '**/*', redirectTo: '', pathMatch: 'full' } ]; diff --git a/src/app/auth/login/login.component.ts b/src/app/auth/login/login.component.ts index 73133c4..1696ef5 100644 --- a/src/app/auth/login/login.component.ts +++ b/src/app/auth/login/login.component.ts @@ -44,7 +44,7 @@ export class LoginComponent implements OnInit { timeOut: 3000, closeButton: true }); - this.router.navigateByUrl('/feed'); + this.router.navigateByUrl('chat'); } }, error: _ => { diff --git a/src/app/chat/chat-routing.module.ts b/src/app/chat/chat-routing.module.ts new file mode 100644 index 0000000..6c7e949 --- /dev/null +++ b/src/app/chat/chat-routing.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { ChatComponent } from './chat/chat.component'; + +const routes: Routes = [ + { path: '', component: ChatComponent }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ChatRoutingModule { } diff --git a/src/app/chat/chat.module.ts b/src/app/chat/chat.module.ts new file mode 100644 index 0000000..05daa1f --- /dev/null +++ b/src/app/chat/chat.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { ChatRoutingModule } from './chat-routing.module'; +import { ChatComponent } from './chat/chat.component'; +import { ChannelListComponent } from './chat/channel-list/channel-list.component'; +import { FeedComponent } from './chat/feed/feed.component'; +import { ChannelEntryComponent } from './chat/channel-list/channel-entry/channel-entry.component'; + + +@NgModule({ + declarations: [ + ChatComponent, + ChannelListComponent, + FeedComponent, + ChannelEntryComponent + ], + imports: [ + CommonModule, + ChatRoutingModule + ] +}) +export class ChatModule { } diff --git a/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.html b/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.html new file mode 100644 index 0000000..766e50b --- /dev/null +++ b/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.html @@ -0,0 +1 @@ +
{{channel.name}}
diff --git a/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.scss b/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.scss new file mode 100644 index 0000000..51cdd88 --- /dev/null +++ b/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.scss @@ -0,0 +1,10 @@ +div { + padding: 5px 10px; + cursor: pointer; +} + +.selected { + color: var(--mat-sys-on-secondary); + background-color: var(--mat-sys-secondary); + transition: all .3s ease-in-out; +} \ No newline at end of file diff --git a/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.ts b/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.ts new file mode 100644 index 0000000..3a53210 --- /dev/null +++ b/src/app/chat/chat/channel-list/channel-entry/channel-entry.component.ts @@ -0,0 +1,13 @@ +import { Component, Input } from '@angular/core'; +import { Channel } from '../../../../models/channel'; + +@Component({ + selector: 'app-channel-entry', + standalone: false, + templateUrl: './channel-entry.component.html', + styleUrl: './channel-entry.component.scss' +}) +export class ChannelEntryComponent { + @Input("channel") public channel!: Channel; + @Input("selected") public selected!: boolean; +} diff --git a/src/app/chat/chat/channel-list/channel-list.component.html b/src/app/chat/chat/channel-list/channel-list.component.html new file mode 100644 index 0000000..22670af --- /dev/null +++ b/src/app/chat/chat/channel-list/channel-list.component.html @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/src/app/chat/chat/channel-list/channel-list.component.scss b/src/app/chat/chat/channel-list/channel-list.component.scss new file mode 100644 index 0000000..e599875 --- /dev/null +++ b/src/app/chat/chat/channel-list/channel-list.component.scss @@ -0,0 +1,4 @@ +:host { + color: var(--mat-sys-on-surface); + background-color: var(--mat-sys-surface); +} \ No newline at end of file diff --git a/src/app/chat/chat/channel-list/channel-list.component.ts b/src/app/chat/chat/channel-list/channel-list.component.ts new file mode 100644 index 0000000..8e63372 --- /dev/null +++ b/src/app/chat/chat/channel-list/channel-list.component.ts @@ -0,0 +1,39 @@ +import { Component, EventEmitter, OnInit, Output } from '@angular/core'; +import { Channel } from '../../../models/channel'; + +@Component({ + selector: 'app-channel-list', + standalone: false, + templateUrl: './channel-list.component.html', + styleUrl: './channel-list.component.scss' +}) +export class ChannelListComponent implements OnInit { + @Output("select") selectEmitter: EventEmitter = new EventEmitter(); + + public channels: Channel[] = [ + { + id: 0, + name: 'default', + description: 'this is the default channel' + }, + { + id: 1, + name: 'gaming', + description: 'this is another channel' + }, + ]; + + public selectedChannel!: Channel; + + constructor() { } + + ngOnInit() { + // TODO: query list of channels + + this.selectedChannel = this.channels[0]; + } + + public Select(index: number): void { + this.selectEmitter.emit(this.selectedChannel = this.channels[index]); + } +} diff --git a/src/app/chat/chat/chat.component.html b/src/app/chat/chat/chat.component.html new file mode 100644 index 0000000..0ab9ea5 --- /dev/null +++ b/src/app/chat/chat/chat.component.html @@ -0,0 +1,4 @@ +
+ + +
\ No newline at end of file diff --git a/src/app/chat/chat/chat.component.scss b/src/app/chat/chat/chat.component.scss new file mode 100644 index 0000000..650d6ca --- /dev/null +++ b/src/app/chat/chat/chat.component.scss @@ -0,0 +1,5 @@ +#container { + display: grid; + grid-template-columns: minmax(auto, 200px) 1fr; + height: 100%; +} \ No newline at end of file diff --git a/src/app/chat/chat/chat.component.ts b/src/app/chat/chat/chat.component.ts new file mode 100644 index 0000000..899bd19 --- /dev/null +++ b/src/app/chat/chat/chat.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { Channel } from '../../models/channel'; + +@Component({ + selector: 'app-chat', + standalone: false, + templateUrl: './chat.component.html', + styleUrl: './chat.component.scss' +}) +export class ChatComponent { + public Select(channel: Channel): void { + // TODO: update feed + } +} diff --git a/src/app/chat/chat/feed/feed.component.html b/src/app/chat/chat/feed/feed.component.html new file mode 100644 index 0000000..e469260 --- /dev/null +++ b/src/app/chat/chat/feed/feed.component.html @@ -0,0 +1 @@ +

feed works!

diff --git a/src/app/chat/chat/feed/feed.component.scss b/src/app/chat/chat/feed/feed.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/chat/chat/feed/feed.component.ts b/src/app/chat/chat/feed/feed.component.ts new file mode 100644 index 0000000..62c16b1 --- /dev/null +++ b/src/app/chat/chat/feed/feed.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-feed', + standalone: false, + templateUrl: './feed.component.html', + styleUrl: './feed.component.scss' +}) +export class FeedComponent { + +} diff --git a/src/app/models/channel.ts b/src/app/models/channel.ts new file mode 100644 index 0000000..2c8c34c --- /dev/null +++ b/src/app/models/channel.ts @@ -0,0 +1,5 @@ +export class Channel { + public id!: number; + public name!: string; + public description!: string; +} \ No newline at end of file diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index a9cfcfb..37e094a 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -1,7 +1,8 @@ -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { inject, Injectable } from '@angular/core'; import { catchError, map, Observable, of } from 'rxjs'; import { LoginResponse, RegisterResponse } from './responses/auth'; +import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot } from '@angular/router'; @Injectable({ providedIn: 'root' @@ -9,6 +10,7 @@ import { LoginResponse, RegisterResponse } from './responses/auth'; export class AuthService { private readonly API_BASE: string = "http://localhost:5000" + private readonly SESSION_COOKIE: string = "session"; private readonly USERNAME_FIELD: string = "username"; private readonly PASSWORD_FIELD: string = "password"; private readonly REPEAT_PASSWORD_FIELD: string = "repeatPassword"; @@ -53,4 +55,21 @@ export class AuthService { catchError(() => of(false)) ); } + + public IsLoggedIn(): boolean { + let cookies = document.cookie.split(';'); + let found = false; + cookies.forEach(cookie => { + cookie = cookie.trim(); + found = found || cookie.startsWith(this.SESSION_COOKIE + "=") && cookie.split('=', 2)[1] != ''; + }); + return found; + } } + +export const IsLoggedInCanActivate: CanActivateFn = ( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot +) => { + return inject(AuthService).IsLoggedIn(); +} \ No newline at end of file