diff --git a/client/src/app/app.routes.ts b/client/src/app/app.routes.ts index a1c4935..19c6dfd 100644 --- a/client/src/app/app.routes.ts +++ b/client/src/app/app.routes.ts @@ -2,6 +2,7 @@ import { Routes } from '@angular/router'; import { ScreenSend } from './screens/screen-send/screen-send'; import { ScreenReceive } from './screens/screen-receive/screen-receive'; import { ScreenProfile } from './screens/screen-profile/screen-profile'; +import { ScreenLogin } from './screens/screen-login/screen-login'; export const routes: Routes = [ { @@ -9,6 +10,10 @@ export const routes: Routes = [ pathMatch:'full', redirectTo: '/send' }, + { + path: 'login', + component: ScreenLogin, + }, { path:'send', component: ScreenSend, diff --git a/client/src/app/screens/screen-login/screen-login.html b/client/src/app/screens/screen-login/screen-login.html new file mode 100644 index 0000000..4185b12 --- /dev/null +++ b/client/src/app/screens/screen-login/screen-login.html @@ -0,0 +1,79 @@ +
+
+
+
+
+
+
+ +

Sign In

+
+ +
+ +
+ + +
+ + +
+ +
+ + +
+
+ + + + + + + + {{ error }} + + +
+
+
+ +
+
+
+
+ diff --git a/client/src/app/screens/screen-login/screen-login.less b/client/src/app/screens/screen-login/screen-login.less new file mode 100644 index 0000000..e69de29 diff --git a/client/src/app/screens/screen-login/screen-login.spec.ts b/client/src/app/screens/screen-login/screen-login.spec.ts new file mode 100644 index 0000000..9596123 --- /dev/null +++ b/client/src/app/screens/screen-login/screen-login.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScreenLogin } from './screen-login'; + +describe('ScreenLogin', () => { + let component: ScreenLogin; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ScreenLogin], + }).compileComponents(); + + fixture = TestBed.createComponent(ScreenLogin); + component = fixture.componentInstance; + await fixture.whenStable(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/screens/screen-login/screen-login.ts b/client/src/app/screens/screen-login/screen-login.ts new file mode 100644 index 0000000..1cf4f1b --- /dev/null +++ b/client/src/app/screens/screen-login/screen-login.ts @@ -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; + } + }); + */ + } +} + diff --git a/package-lock.json b/package-lock.json index 5e4274c..a4d92f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5564,6 +5564,25 @@ "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": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", @@ -7243,10 +7262,9 @@ } }, "node_modules/jose": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", - "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", - "dev": true, + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.0.tgz", + "integrity": "sha512-xsfE1TcSCbUdo6U07tR0mvhg0flGxU8tPLbF03mirl2ukGQENhUg4ubGYQnhVH0b5stLlPM+WOqDkEl1R1y5sQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" @@ -10442,6 +10460,18 @@ "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": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -11261,6 +11291,7 @@ "version": "1.0.0", "license": "GPL-3.0", "dependencies": { + "cookie-parser": "^1.4.7", "cors": "^2.8.6", "dotenv": "^17.3.1", "express": "^5.2.1", @@ -11269,6 +11300,7 @@ "reflect-metadata": "^0.2.2", "sequelize": "^6.37.7", "sequelize-typescript": "^2.1.6", + "ts-jose": "^6.2.0", "winston": "^3.19.0" }, "devDependencies": { diff --git a/package.json b/package.json index 6e390f0..bf335eb 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ }, "workspaces": [ "client", - "server", - "shared" + "server" ], "devDependencies": { "@types/node": "^25.3.2", diff --git a/server/package.json b/server/package.json index f6cf9e2..14da443 100644 --- a/server/package.json +++ b/server/package.json @@ -17,6 +17,7 @@ "dev": "npm run setup && npm run node; npm run teardown" }, "dependencies": { + "cookie-parser": "^1.4.7", "cors": "^2.8.6", "dotenv": "^17.3.1", "express": "^5.2.1", @@ -25,6 +26,7 @@ "reflect-metadata": "^0.2.2", "sequelize": "^6.37.7", "sequelize-typescript": "^2.1.6", + "ts-jose": "^6.2.0", "winston": "^3.19.0" }, "devDependencies": { diff --git a/shared/package.json b/shared/package.json deleted file mode 100644 index 45fa91c..0000000 --- a/shared/package.json +++ /dev/null @@ -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": {} -} diff --git a/shared/src/interfaces/transaction.ts b/shared/src/interfaces/transaction.ts deleted file mode 100644 index dcf4823..0000000 --- a/shared/src/interfaces/transaction.ts +++ /dev/null @@ -1,8 +0,0 @@ - -export interface Transaction { - id: string; - partner: string; - amount: number; - date: Date; - type: 'Sent' | 'Received'; -} \ No newline at end of file diff --git a/shared/tsconfig.json b/shared/tsconfig.json deleted file mode 100644 index 73c85e4..0000000 --- a/shared/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../dist/out-tsc/shared", - "declaration": true, - "module": "es2020" - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules"] -}