begin auth
This commit is contained in:
@@ -2,6 +2,7 @@ import { Routes } from '@angular/router';
|
|||||||
import { ScreenSend } from './screens/screen-send/screen-send';
|
import { ScreenSend } from './screens/screen-send/screen-send';
|
||||||
import { ScreenReceive } from './screens/screen-receive/screen-receive';
|
import { ScreenReceive } from './screens/screen-receive/screen-receive';
|
||||||
import { ScreenProfile } from './screens/screen-profile/screen-profile';
|
import { ScreenProfile } from './screens/screen-profile/screen-profile';
|
||||||
|
import { ScreenLogin } from './screens/screen-login/screen-login';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{
|
{
|
||||||
@@ -9,6 +10,10 @@ export const routes: Routes = [
|
|||||||
pathMatch:'full',
|
pathMatch:'full',
|
||||||
redirectTo: '/send'
|
redirectTo: '/send'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'login',
|
||||||
|
component: ScreenLogin,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path:'send',
|
path:'send',
|
||||||
component: ScreenSend,
|
component: ScreenSend,
|
||||||
|
|||||||
79
client/src/app/screens/screen-login/screen-login.html
Normal file
79
client/src/app/screens/screen-login/screen-login.html
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<div class="d-flex align-items-center min-vh-100 bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-4 col-md-6 col-sm-8">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="text-center mb-4">
|
||||||
|
<i class="bi bi-lock-fill fs-1 text-primary"></i>
|
||||||
|
<h3 class="mt-2">Sign In</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()" novalidate>
|
||||||
|
<!-- Email -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label">Email</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="username"
|
||||||
|
class="form-control"
|
||||||
|
formControlName="username"
|
||||||
|
placeholder="Enter your username"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Password -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Password</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input
|
||||||
|
[type]="showPassword ? 'text' : 'password'"
|
||||||
|
id="password"
|
||||||
|
class="form-control"
|
||||||
|
formControlName="password"
|
||||||
|
placeholder="Enter your password"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-secondary"
|
||||||
|
type="button"
|
||||||
|
(click)="showPassword = !showPassword"
|
||||||
|
>
|
||||||
|
<i class="bi" [class.bi-eye-fill]="showPassword" [class.bi-eye-slash-fill]="!showPassword"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Submit Button -->
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-primary w-100 mb-3"
|
||||||
|
>
|
||||||
|
@if (loading) {
|
||||||
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true">
|
||||||
|
Signing In...
|
||||||
|
</span>
|
||||||
|
}@else {
|
||||||
|
<span>Sign In</span>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Error Alert -->
|
||||||
|
<ngb-alert
|
||||||
|
*ngIf="error"
|
||||||
|
type="danger"
|
||||||
|
(closed)="error = null"
|
||||||
|
[dismissible]="true"
|
||||||
|
>
|
||||||
|
{{ error }}
|
||||||
|
</ngb-alert>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
22
client/src/app/screens/screen-login/screen-login.spec.ts
Normal file
22
client/src/app/screens/screen-login/screen-login.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ScreenLogin } from './screen-login';
|
||||||
|
|
||||||
|
describe('ScreenLogin', () => {
|
||||||
|
let component: ScreenLogin;
|
||||||
|
let fixture: ComponentFixture<ScreenLogin>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [ScreenLogin],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ScreenLogin);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
55
client/src/app/screens/screen-login/screen-login.ts
Normal file
55
client/src/app/screens/screen-login/screen-login.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { Validators, FormBuilder, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-screen-login',
|
||||||
|
imports: [FormsModule, NgbModule, ReactiveFormsModule, CommonModule],
|
||||||
|
templateUrl: './screen-login.html',
|
||||||
|
styleUrl: './screen-login.less',
|
||||||
|
})
|
||||||
|
export class ScreenLogin {
|
||||||
|
loginForm: FormGroup;
|
||||||
|
submitted = false;
|
||||||
|
loading = false;
|
||||||
|
showPassword = false;
|
||||||
|
error: string | null = null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
this.loginForm = this.fb.group({
|
||||||
|
email: ['', [Validators.required, Validators.email]],
|
||||||
|
password: ['', [Validators.required, Validators.minLength(6)]],
|
||||||
|
rememberMe: [false]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.submitted = true;
|
||||||
|
this.error = null;
|
||||||
|
|
||||||
|
if (this.loginForm.invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
const { email, password, rememberMe } = this.loginForm.value;
|
||||||
|
|
||||||
|
/*
|
||||||
|
this.authService.login(email, password, rememberMe).subscribe({
|
||||||
|
next: () => {
|
||||||
|
this.router.navigate(['/dashboard']); // Redirect after login
|
||||||
|
},
|
||||||
|
error: (err) => {
|
||||||
|
this.error = err.error?.message || 'Login failed. Please try again.';
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
40
package-lock.json
generated
40
package-lock.json
generated
@@ -5564,6 +5564,25 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cookie-parser": {
|
||||||
|
"version": "1.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
|
||||||
|
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": "0.7.2",
|
||||||
|
"cookie-signature": "1.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie-parser/node_modules/cookie-signature": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/cookie-signature": {
|
"node_modules/cookie-signature": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
|
||||||
@@ -7243,10 +7262,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jose": {
|
"node_modules/jose": {
|
||||||
"version": "6.1.3",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/jose/-/jose-6.2.0.tgz",
|
||||||
"integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==",
|
"integrity": "sha512-xsfE1TcSCbUdo6U07tR0mvhg0flGxU8tPLbF03mirl2ukGQENhUg4ubGYQnhVH0b5stLlPM+WOqDkEl1R1y5sQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/panva"
|
"url": "https://github.com/sponsors/panva"
|
||||||
@@ -10442,6 +10460,18 @@
|
|||||||
"node": ">= 14.0.0"
|
"node": ">= 14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ts-jose": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-jose/-/ts-jose-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-KbuVu70utxPDrfjbPyjEs63GLA6ogBZlr7joyFmO/IvNWjwINa4LoZa5LhG/lp9Y8zb8HEkSTaAOCdnqIeMGqA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jose": "6.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-node": {
|
"node_modules/ts-node": {
|
||||||
"version": "10.9.2",
|
"version": "10.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||||
@@ -11261,6 +11291,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cookie-parser": "^1.4.7",
|
||||||
"cors": "^2.8.6",
|
"cors": "^2.8.6",
|
||||||
"dotenv": "^17.3.1",
|
"dotenv": "^17.3.1",
|
||||||
"express": "^5.2.1",
|
"express": "^5.2.1",
|
||||||
@@ -11269,6 +11300,7 @@
|
|||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"sequelize": "^6.37.7",
|
"sequelize": "^6.37.7",
|
||||||
"sequelize-typescript": "^2.1.6",
|
"sequelize-typescript": "^2.1.6",
|
||||||
|
"ts-jose": "^6.2.0",
|
||||||
"winston": "^3.19.0"
|
"winston": "^3.19.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -13,8 +13,7 @@
|
|||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"client",
|
"client",
|
||||||
"server",
|
"server"
|
||||||
"shared"
|
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^25.3.2",
|
"@types/node": "^25.3.2",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"dev": "npm run setup && npm run node; npm run teardown"
|
"dev": "npm run setup && npm run node; npm run teardown"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cookie-parser": "^1.4.7",
|
||||||
"cors": "^2.8.6",
|
"cors": "^2.8.6",
|
||||||
"dotenv": "^17.3.1",
|
"dotenv": "^17.3.1",
|
||||||
"express": "^5.2.1",
|
"express": "^5.2.1",
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"sequelize": "^6.37.7",
|
"sequelize": "^6.37.7",
|
||||||
"sequelize-typescript": "^2.1.6",
|
"sequelize-typescript": "^2.1.6",
|
||||||
|
"ts-jose": "^6.2.0",
|
||||||
"winston": "^3.19.0"
|
"winston": "^3.19.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "shared",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"license": "GPL-3.0",
|
|
||||||
"author": "",
|
|
||||||
"type": "commonjs",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"devDependencies": {}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
export interface Transaction {
|
|
||||||
id: string;
|
|
||||||
partner: string;
|
|
||||||
amount: number;
|
|
||||||
date: Date;
|
|
||||||
type: 'Sent' | 'Received';
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../dist/out-tsc/shared",
|
|
||||||
"declaration": true,
|
|
||||||
"module": "es2020"
|
|
||||||
},
|
|
||||||
"include": ["src/**/*.ts"],
|
|
||||||
"exclude": ["node_modules"]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user