diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1c0ed6fb..a51f916c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -9,7 +9,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - + - name: Setup Bun uses: oven-sh/setup-bun@v1 @@ -23,4 +23,64 @@ jobs: uses: actions/upload-artifact@v4 with: name: Build-artifacts - path: dist/ \ No newline at end of file + path: dist/ + + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v1 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Lint + run: bun run lint + + unit-tests: + if: ${{ github.event_name == 'pull_request' }} + name: Unit tests + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v1 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Unit tests + run: bun run test --no-watch --no-progress --browsers=ChromeHeadless + + + unit-tests-upload: + # This job uses a secret + # Pull requests are untrusted + if: ${{ github.event_name == 'push' }} + name: Unit tests and upload to Codecov + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v1 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Unit tests + run: bun run test --no-watch --no-progress --browsers=ChromeHeadless + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1f1ceb9f..34a6d49e 100644 --- a/.gitignore +++ b/.gitignore @@ -99,3 +99,7 @@ storage.rules /.next/ /out/ next-env.d.ts +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 16099026..9b4ce3b8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,8 @@ // Disable editor indentation detection "editor.insertSpaces": true, "editor.tabSize": 2, - "editor.detectIndentation": false + "editor.detectIndentation": false, + + // ESLint + "eslint.useFlatConfig": false } diff --git a/angular.json b/angular.json index ce4a4d73..6bd34947 100644 --- a/angular.json +++ b/angular.json @@ -99,15 +99,17 @@ "test": { "builder": "@angular-devkit/build-angular:karma", "options": { - "main": "src/test.ts", + "codeCoverage": true, "polyfills": [ "zone.js", "zone.js/testing" ], "tsConfig": "tsconfig.spec.json", - "karmaConfig": "karma.conf.js", "styles": [], "scripts": [], + "exclude": [ + "src/app/unused/**/*.ts" + ], "assets": [ { "glob": "favicon.ico", @@ -119,7 +121,8 @@ "input": "src/assets", "output": "/assets" } - ] + ], + "karmaConfig": "karma.conf.js" }, "configurations": { "ci": { diff --git a/bun.lockb b/bun.lockb index 17fa0118..c43a6468 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..308f2588 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,45 @@ +// @ts-check +const eslint = require('@eslint/js'); +const tseslint = require('typescript-eslint'); +const angular = require('angular-eslint'); + +module.exports = tseslint.config( + { + files: ['**/*.ts'], + extends: [ + eslint.configs.recommended, + ...tseslint.configs.recommended, + ...tseslint.configs.stylistic, + ...angular.configs.tsRecommended, + ], + processor: angular.processInlineTemplates, + rules: { + '@angular-eslint/directive-selector': [ + 'error', + { + type: 'attribute', + prefix: 'app', + style: 'camelCase', + }, + ], + '@angular-eslint/component-selector': [ + 'error', + { + type: 'element', + prefix: 'app', + style: 'kebab-case', + }, + ], + '@angular-eslint/component-class-suffix': 'off', + '@typescript-eslint/consistent-indexed-object-style': ['error', 'record'], + }, + }, + { + files: ['**/*.html'], + extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], + rules: {}, + }, + { + ignores: ['functions/*', 'src/app/unused/*'], + } +); diff --git a/functions/src/certificates/issue-certificate.ts b/functions/src/certificates/issue-certificate.ts index 922e189a..2b3fab12 100644 --- a/functions/src/certificates/issue-certificate.ts +++ b/functions/src/certificates/issue-certificate.ts @@ -11,7 +11,7 @@ exports.issueMajorEventCertificate = onCall( const data: MajorEventCertificateData = request.data; const context = request; - if (context.app == undefined) { + if (context.app === undefined) { throw new HttpsError('failed-precondition', 'The function must be called from an App Check verified app.'); } diff --git a/functions/src/claims/claims.ts b/functions/src/claims/claims.ts index d5b9c546..326893bd 100644 --- a/functions/src/claims/claims.ts +++ b/functions/src/claims/claims.ts @@ -8,7 +8,7 @@ import { log } from 'firebase-functions/logger'; exports.addAdminRole = onCall(async (request): Promise => { const data = request.data; const context = request; - if (context.app == undefined) { + if (context.app === undefined) { throw new HttpsError('failed-precondition', 'The function must be called from an App Check verified app.'); } @@ -50,7 +50,7 @@ exports.removeAdminRole = onCall(async (request): Promise => { const context = request; const remoteConfig = getRemoteConfig(); - if (context.app == undefined) { + if (context.app === undefined) { throw new HttpsError('failed-precondition', 'The function must be called from an App Check verified app.'); } @@ -65,7 +65,7 @@ exports.removeAdminRole = onCall(async (request): Promise => { // Get whitelist array as string from remote config const template = await remoteConfig.getTemplate(); - // @ts-ignore + // @ts-expect-error const whitelist: string = template.parameters.adminWhitelist.defaultValue?.value; // Check if email is included in whitelist array if (whitelist.includes(data.email)) { @@ -110,7 +110,7 @@ exports.addProfessorRole = onCall(async (request): Promise => { const context = request; const db = getFirestore(); - if (context.app == undefined) { + if (context.app === undefined) { throw new HttpsError('failed-precondition', 'The function must be called from an App Check verified app.'); } @@ -128,7 +128,7 @@ exports.addProfessorRole = onCall(async (request): Promise => { return remoteConfig .getTemplate() .then((template) => { - // @ts-ignore + // @ts-expect-error const professors: string = template.parameters.professors.defaultValue?.value; // Check if email is included in professors array diff --git a/functions/src/unused/move-certificates.ts b/functions/src/unused/move-certificates.ts index 2fcc9401..13aa2f8c 100644 --- a/functions/src/unused/move-certificates.ts +++ b/functions/src/unused/move-certificates.ts @@ -7,7 +7,7 @@ exports.moveCertificates = onCall({ timeoutSeconds: 540, memory: '1GiB' }, async throw new HttpsError('failed-precondition', 'The function must be called while authenticated.'); } - if (context.app == undefined) { + if (context.app === undefined) { throw new HttpsError('failed-precondition', 'The function must be called from an App Check verified app.'); } diff --git a/functions/src/utils/user/impersonate.ts b/functions/src/utils/user/impersonate.ts index 2e3499f7..06715704 100644 --- a/functions/src/utils/user/impersonate.ts +++ b/functions/src/utils/user/impersonate.ts @@ -3,7 +3,7 @@ // Attribution: amiregelz // https://stackoverflow.com/questions/36759627/firebase-login-as-other-user/71808501#71808501 /*exports.impersonate = functions.https.onCall((data, context) => { - if (context.app == undefined) { + if (context.app===undefined) { throw new functions.https.HttpsError( 'failed-precondition', 'The function must be called from an App Check verified app.' @@ -20,7 +20,7 @@ // Get whitelist array as string from remote config return remoteConfig.getTemplate().then((template) => { - // @ts-ignore + // @ts-expect-error const whitelist: string = template.parameters.adminWhitelist.defaultValue?.value; if (context.auth?.uid) { diff --git a/functions/src/utils/user/user-utils.ts b/functions/src/utils/user/user-utils.ts index ddab1712..3c52fcbc 100644 --- a/functions/src/utils/user/user-utils.ts +++ b/functions/src/utils/user/user-utils.ts @@ -12,7 +12,7 @@ exports.getUserUid = onCall(async (context): Promise => { throw new HttpsError('failed-precondition', 'The function must be called while authenticated.'); } - if (context.app == undefined) { + if (context.app === undefined) { throw new HttpsError('failed-precondition', 'The function must be called from an App Check verified app.'); } diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 00000000..2236bd98 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,40 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma'), + ], + preprocessors: { + 'src/**/*.ts': ['coverage'], + }, + + client: { + jasmine: { + // you can add configuration options for Jasmine here + // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html + // for example, you can disable the random execution with `random: false` + // or set a specific seed with `seed: 4321` + }, + clearContext: false, // leave Jasmine Spec Runner output visible in browser + }, + jasmineHtmlReporter: { + suppressAll: true, // removes the duplicated traces + }, + coverageReporter: { + dir: require('path').join(__dirname, './coverage/app'), + subdir: '.', + reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'lcovonly' }], + }, + reporters: ['progress', 'kjhtml', 'coverage'], + browsers: ['Chrome'], + restartOnFileChange: true, + }); +}; diff --git a/package.json b/package.json index c9a80ce6..e4e961fa 100644 --- a/package.json +++ b/package.json @@ -10,28 +10,28 @@ "build": "ng build", "test": "ng test", "lint": "ng lint", - "e2e": "ng e2e" + "e2e": "playwright test" }, "private": true, "dependencies": { - "@angular/animations": "18.0.0", - "@angular/common": "~18.0.0", - "@angular/core": "~18.0.0", + "@angular/animations": "18.0.1", + "@angular/common": "~18.0.1", + "@angular/core": "~18.0.1", "@angular/fire": "^18.0.1", - "@angular/forms": "~18.0.0", - "@angular/platform-browser": "~18.0.0", - "@angular/platform-browser-dynamic": "~18.0.0", - "@angular/router": "~18.0.0", - "@angular/service-worker": "^18.0.0", + "@angular/forms": "~18.0.1", + "@angular/platform-browser": "~18.0.1", + "@angular/platform-browser-dynamic": "~18.0.1", + "@angular/router": "~18.0.1", + "@angular/service-worker": "^18.0.1", "@ionic/angular": "^8.2.0", "@ngneat/until-destroy": "^10.0.0", "@notiz/ngx-plausible": "^0.7.0", - "@pdfme/generator": "^4.0.1", + "@pdfme/generator": "^4.0.2", "@sweetalert2/ngx-sweetalert2": "^12.3.0", "buffer": "^6.0.3", "bwip-js": "^4.3.2", "date-fns": "^3.6.0", - "highlight.run": "^8.12.3", + "highlight.run": "^8.13.0", "ionicons": "^7.4.0", "marked": "^12.0.2", "ngx-image-compress": "^15.1.6", @@ -45,26 +45,33 @@ "zxing-wasm": "^1.2.10" }, "devDependencies": { - "@angular-devkit/build-angular": "~18.0.1", - "@angular-eslint/builder": "~17.5.1", - "@angular-eslint/eslint-plugin": "~17.5.1", - "@angular-eslint/eslint-plugin-template": "~17.5.1", - "@angular-eslint/template-parser": "~17.5.1", - "@angular/cli": "~18.0.1", - "@angular/compiler": "~18.0.0", - "@angular/compiler-cli": "~18.0.0", - "@angular/language-service": "~18.0.0", + "@angular-devkit/build-angular": "~18.0.2", + "@angular/cli": "~18.0.2", + "@angular/compiler": "~18.0.1", + "@angular/compiler-cli": "~18.0.1", + "@angular/language-service": "~18.0.1", "@ionic/angular-toolkit": "^11.0.1", - "@pdfme/common": "^4.0.1", - "@pdfme/schemas": "^4.0.1", - "@typescript-eslint/eslint-plugin": "7.11.0", - "@typescript-eslint/parser": "7.11.0", + "@pdfme/common": "^4.0.2", + "@pdfme/schemas": "^4.0.2", + "@playwright/test": "^1.44.1", "@types/google-one-tap": "^1.2.6", + "@types/jasmine": "^5.1.4", + "@types/jest": "^29.5.12", + "@types/node": "^20.13.0", "@types/twemoji-parser": "^13.1.4", + "@web/test-runner": "^0.18.2", + "angular-eslint": "18.0.1", "eslint": "^9.3.0", "eslint-plugin-import": "2.29.1", - "eslint-plugin-jsdoc": "48.2.6", + "eslint-plugin-jsdoc": "48.2.7", "eslint-plugin-prefer-arrow": "1.2.3", + "jasmine": "^5.1.0", + "jest-preset-angular": "^14.1.0", + "karma": "^6.4.3", + "karma-chrome-launcher": "^3.2.0", + "karma-coverage": "^2.2.1", + "karma-jasmine": "^5.1.0", + "karma-jasmine-html-reporter": "^2.1.0", "protractor": "~7.0.0", "react": "^18.3.1", "react-dom": "18.3.1", @@ -72,6 +79,7 @@ "ts-node": "~10.9.2", "tslib": "^2.6.2", "typescript": "5.4.5", + "typescript-eslint": "8.0.0-alpha.20", "typescript-strict-plugin": "^2.4.3" }, "trustedDependencies": [ diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..301801ee --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,77 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/src/app/about/about.page.ts b/src/app/about/about.page.ts index bdb54923..fe73c633 100644 --- a/src/app/about/about.page.ts +++ b/src/app/about/about.page.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { GlobalConstantsService } from '../shared/services/global-constants.service'; import { RouterLink } from '@angular/router'; import { @@ -33,10 +33,6 @@ import { IonCol, ], }) -export class AboutPage implements OnInit { +export class AboutPage { globalConstants = GlobalConstantsService; - - constructor() {} - - ngOnInit() {} } diff --git a/src/app/about/licenses/licenses.page.ts b/src/app/about/licenses/licenses.page.ts index fae29923..fa4d2e69 100644 --- a/src/app/about/licenses/licenses.page.ts +++ b/src/app/about/licenses/licenses.page.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { DisplayLicensesComponent } from './display-licenses/display-licenses.component'; import { MarkdownModule } from 'ngx-markdown'; import { IonHeader, IonToolbar, IonButtons, IonBackButton, IonTitle, IonContent } from '@ionic/angular/standalone'; @@ -19,8 +19,4 @@ import { IonHeader, IonToolbar, IonButtons, IonBackButton, IonTitle, IonContent IonContent, ], }) -export class LicensesPage implements OnInit { - constructor() {} - - ngOnInit() {} -} +export class LicensesPage {} diff --git a/src/app/about/licenses/licenses.routes.ts b/src/app/about/licenses/licenses.routes.ts index 212108eb..3998cbda 100644 --- a/src/app/about/licenses/licenses.routes.ts +++ b/src/app/about/licenses/licenses.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { LicensesPage } from './licenses.page'; diff --git a/src/app/about/privacy-policy/privacy-cards/linked-data/linked-data.component.spec.ts b/src/app/about/privacy-policy/privacy-cards/linked-data/linked-data.component.spec.ts deleted file mode 100644 index 3693226d..00000000 --- a/src/app/about/privacy-policy/privacy-cards/linked-data/linked-data.component.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; - -import { LinkedDataComponent } from './linked-data.component'; - -describe('LinkedDataComponent', () => { - let component: LinkedDataComponent; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [LinkedDataComponent], - }).compileComponents(); - - fixture = TestBed.createComponent(LinkedDataComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - })); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/about/privacy-policy/privacy-cards/linked-data/linked-data.component.ts b/src/app/about/privacy-policy/privacy-cards/linked-data/linked-data.component.ts index c757f7af..9bba8ab2 100644 --- a/src/app/about/privacy-policy/privacy-cards/linked-data/linked-data.component.ts +++ b/src/app/about/privacy-policy/privacy-cards/linked-data/linked-data.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { IonLabel, IonList, IonItem, IonIcon, IonNote } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { @@ -19,7 +19,7 @@ import { imports: [IonNote, IonIcon, IonList, IonItem, IonLabel], standalone: true, }) -export class LinkedDataComponent implements OnInit { +export class LinkedDataComponent { constructor() { addIcons({ schoolOutline, @@ -32,6 +32,4 @@ export class LinkedDataComponent implements OnInit { personCircleOutline, }); } - - ngOnInit() {} } diff --git a/src/app/about/privacy-policy/privacy-cards/not-linked-data/not-linked-data.component.spec.ts b/src/app/about/privacy-policy/privacy-cards/not-linked-data/not-linked-data.component.spec.ts deleted file mode 100644 index c03057bc..00000000 --- a/src/app/about/privacy-policy/privacy-cards/not-linked-data/not-linked-data.component.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; - -import { NotLinkedDataComponent } from './not-linked-data.component'; - -describe('NotLinkedDataComponent', () => { - let component: NotLinkedDataComponent; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [NotLinkedDataComponent], - }).compileComponents(); - - fixture = TestBed.createComponent(NotLinkedDataComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - })); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/about/privacy-policy/privacy-cards/not-linked-data/not-linked-data.component.ts b/src/app/about/privacy-policy/privacy-cards/not-linked-data/not-linked-data.component.ts index 4dad31c6..3cb3e262 100644 --- a/src/app/about/privacy-policy/privacy-cards/not-linked-data/not-linked-data.component.ts +++ b/src/app/about/privacy-policy/privacy-cards/not-linked-data/not-linked-data.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { IonList, IonItem, IonLabel, IonIcon, IonNote } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { analyticsOutline, ellipsisHorizontalCircleOutline, navigateOutline, searchOutline } from 'ionicons/icons'; @@ -10,7 +10,7 @@ import { analyticsOutline, ellipsisHorizontalCircleOutline, navigateOutline, sea imports: [IonList, IonItem, IonLabel, IonIcon, IonNote], standalone: true, }) -export class NotLinkedDataComponent implements OnInit { +export class NotLinkedDataComponent { constructor() { addIcons({ navigateOutline, @@ -19,6 +19,4 @@ export class NotLinkedDataComponent implements OnInit { ellipsisHorizontalCircleOutline, }); } - - ngOnInit() {} } diff --git a/src/app/about/privacy-policy/privacy-cards/privacy-cards.component.spec.ts b/src/app/about/privacy-policy/privacy-cards/privacy-cards.component.spec.ts deleted file mode 100644 index 3c500382..00000000 --- a/src/app/about/privacy-policy/privacy-cards/privacy-cards.component.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; - -import { PrivacyCardsComponent } from './privacy-cards.component'; - -describe('PrivacyCardsComponent', () => { - let component: PrivacyCardsComponent; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [PrivacyCardsComponent], - }).compileComponents(); - - fixture = TestBed.createComponent(PrivacyCardsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - })); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/about/privacy-policy/privacy-cards/privacy-cards.component.ts b/src/app/about/privacy-policy/privacy-cards/privacy-cards.component.ts index 96b8ca6b..19d369d1 100644 --- a/src/app/about/privacy-policy/privacy-cards/privacy-cards.component.ts +++ b/src/app/about/privacy-policy/privacy-cards/privacy-cards.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { IonList, IonItem } from '@ionic/angular/standalone'; import { LinkedDataComponent } from 'src/app/about/privacy-policy/privacy-cards/linked-data/linked-data.component'; import { NotLinkedDataComponent } from 'src/app/about/privacy-policy/privacy-cards/not-linked-data/not-linked-data.component'; @@ -11,8 +11,4 @@ import { TrackingDataComponent } from 'src/app/about/privacy-policy/privacy-card imports: [IonItem, IonList, LinkedDataComponent, NotLinkedDataComponent, TrackingDataComponent], standalone: true, }) -export class PrivacyCardsComponent implements OnInit { - constructor() {} - - ngOnInit() {} -} +export class PrivacyCardsComponent {} diff --git a/src/app/about/privacy-policy/privacy-cards/tracking-data/tracking-data.component.spec.ts b/src/app/about/privacy-policy/privacy-cards/tracking-data/tracking-data.component.spec.ts deleted file mode 100644 index ff1142d0..00000000 --- a/src/app/about/privacy-policy/privacy-cards/tracking-data/tracking-data.component.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; - -import { TrackingDataComponent } from './tracking-data.component'; - -describe('TrackingDataComponent', () => { - let component: TrackingDataComponent; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [TrackingDataComponent], - }).compileComponents(); - - fixture = TestBed.createComponent(TrackingDataComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - })); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/about/privacy-policy/privacy-cards/tracking-data/tracking-data.component.ts b/src/app/about/privacy-policy/privacy-cards/tracking-data/tracking-data.component.ts index b85c9a2d..feaf5307 100644 --- a/src/app/about/privacy-policy/privacy-cards/tracking-data/tracking-data.component.ts +++ b/src/app/about/privacy-policy/privacy-cards/tracking-data/tracking-data.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { IonItem, IonIcon, IonLabel, IonList, IonNote } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { analyticsOutline, fingerPrintOutline, idCardOutline, searchOutline } from 'ionicons/icons'; @@ -10,7 +10,7 @@ import { analyticsOutline, fingerPrintOutline, idCardOutline, searchOutline } fr standalone: true, imports: [IonNote, IonList, IonItem, IonIcon, IonLabel], }) -export class TrackingDataComponent implements OnInit { +export class TrackingDataComponent { constructor() { addIcons({ fingerPrintOutline, @@ -19,6 +19,4 @@ export class TrackingDataComponent implements OnInit { idCardOutline, }); } - - ngOnInit() {} } diff --git a/src/app/about/privacy-policy/privacy-policy.page.ts b/src/app/about/privacy-policy/privacy-policy.page.ts index 12d4ada7..45dfaa91 100644 --- a/src/app/about/privacy-policy/privacy-policy.page.ts +++ b/src/app/about/privacy-policy/privacy-policy.page.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { PrivacyCardsComponent } from 'src/app/about/privacy-policy/privacy-cards/privacy-cards.component'; import { environment } from 'src/environments/environment'; @@ -21,9 +21,6 @@ import { MarkdownModule } from 'ngx-markdown'; MarkdownModule, ], }) -export class PrivacyPolicyPage implements OnInit { +export class PrivacyPolicyPage { public baseUrl = environment.baseUrl; - constructor() {} - - ngOnInit() {} } diff --git a/src/app/about/privacy-policy/privacy-policy.routes.ts b/src/app/about/privacy-policy/privacy-policy.routes.ts index 388ed709..0a4c4748 100644 --- a/src/app/about/privacy-policy/privacy-policy.routes.ts +++ b/src/app/about/privacy-policy/privacy-policy.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { PrivacyPolicyPage } from './privacy-policy.page'; diff --git a/src/app/about/support/support.page.ts b/src/app/about/support/support.page.ts index 29e2c728..251ebc38 100644 --- a/src/app/about/support/support.page.ts +++ b/src/app/about/support/support.page.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { AlertController } from '@ionic/angular/standalone'; import { @@ -42,8 +42,8 @@ import { ServiceWorkerService } from 'src/app/shared/services/service-worker/ser IonText, ], }) -export class SupportPage implements OnInit { - serviceWorkerActive: boolean = false; +export class SupportPage { + serviceWorkerActive = false; constructor( private alertController: AlertController, @@ -52,8 +52,6 @@ export class SupportPage implements OnInit { this.serviceWorkerActive = this.sw.getServiceWorkerStatus(); } - ngOnInit() {} - async alertUpdate() { const alert = await this.alertController.create({ header: 'Atualizar o aplicativo', diff --git a/src/app/about/support/support.routes.ts b/src/app/about/support/support.routes.ts index e74fbad0..8106e730 100644 --- a/src/app/about/support/support.routes.ts +++ b/src/app/about/support/support.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { SupportPage } from './support.page'; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 28aa8911..afb45481 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,5 +1,5 @@ import { canActivate } from '@angular/fire/compat/auth-guard'; -import { RouteReuseStrategy, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { DevelopmentOnlyGuard, diff --git a/src/app/auth/login/components/google-button/google-button.component.ts b/src/app/auth/login/components/google-button/google-button.component.ts index 58d9bf75..38ec9b50 100644 --- a/src/app/auth/login/components/google-button/google-button.component.ts +++ b/src/app/auth/login/components/google-button/google-button.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, WritableSignal, signal } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, ViewChild, WritableSignal, signal } from '@angular/core'; import { AuthService } from 'src/app/shared/services/auth.service'; import { CredentialResponse } from 'google-one-tap'; import { environment } from 'src/environments/environment'; @@ -27,7 +27,7 @@ export class GoogleButtonComponent implements AfterViewInit { ngAfterViewInit() { if (environment.production) { - //@ts-ignore + //@ts-expect-error - google is defined by the script in index.html google.accounts.id.initialize({ // Ref: https://developers.google.com/identity/gsi/web/reference/js-reference#IdConfiguration client_id: '169157391934-n61n94q5pdv1uloqnejher4v9fudd9g7.apps.googleusercontent.com', @@ -36,7 +36,7 @@ export class GoogleButtonComponent implements AfterViewInit { cancel_on_tap_outside: false, }); - //@ts-ignore + //@ts-expect-error - google is defined by the script in index.html google.accounts.id.renderButton(this.googleButton.nativeElement, { theme: 'outline', size: 'large', diff --git a/src/app/auth/login/login.page.ts b/src/app/auth/login/login.page.ts index a6c711be..e818e6f6 100644 --- a/src/app/auth/login/login.page.ts +++ b/src/app/auth/login/login.page.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { RouterLink } from '@angular/router'; import { GoogleButtonComponent } from './components/google-button/google-button.component'; import { @@ -34,8 +34,4 @@ import { IonCol, ], }) -export class LoginPage implements OnInit { - constructor() {} - - ngOnInit() {} -} +export class LoginPage {} diff --git a/src/app/development-tools/development-tools.page.ts b/src/app/development-tools/development-tools.page.ts index 6eced70e..44bf348e 100644 --- a/src/app/development-tools/development-tools.page.ts +++ b/src/app/development-tools/development-tools.page.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { RouterLink } from '@angular/router'; import { addIcons } from 'ionicons'; import { serverOutline } from 'ionicons/icons'; @@ -36,10 +36,8 @@ import { IonLabel, ], }) -export class DevelopmentToolsPage implements OnInit { +export class DevelopmentToolsPage { constructor() { addIcons({ serverOutline }); } - - ngOnInit() {} } diff --git a/src/app/development-tools/populate-database/populate-database.page.ts b/src/app/development-tools/populate-database/populate-database.page.ts index 3e079f11..11c2564a 100644 --- a/src/app/development-tools/populate-database/populate-database.page.ts +++ b/src/app/development-tools/populate-database/populate-database.page.ts @@ -56,11 +56,11 @@ export class PopulateDatabasePage implements OnInit { parseFloat = parseFloat; dataForm: FormGroup; - progress: number = 0; + progress = 0; - populateStarted: boolean = false; + populateStarted = false; - numberOfSelectedCheckboxes: number = 0; + numberOfSelectedCheckboxes = 0; progressPerItem: number; constructor(private formBuilder: FormBuilder) { diff --git a/src/app/development-tools/populate-database/populate-database.routes.ts b/src/app/development-tools/populate-database/populate-database.routes.ts index 8967731b..f76772e5 100644 --- a/src/app/development-tools/populate-database/populate-database.routes.ts +++ b/src/app/development-tools/populate-database/populate-database.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { PopulateDatabasePage } from './populate-database.page'; diff --git a/src/app/landing/landing.page.html b/src/app/landing/landing.page.html index 92de550c..39878a3a 100644 --- a/src/app/landing/landing.page.html +++ b/src/app/landing/landing.page.html @@ -35,7 +35,7 @@

Gerencie eventos universitários de forma simples

-
+

Veja o que você pode fazer com o FCT App

diff --git a/src/app/landing/landing.page.ts b/src/app/landing/landing.page.ts index 2b417d2d..94b3d6ef 100644 --- a/src/app/landing/landing.page.ts +++ b/src/app/landing/landing.page.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { @@ -38,13 +38,9 @@ import { Router, RouterLink } from '@angular/router'; RouterLink, ], }) -export class LandingPage implements OnInit { +export class LandingPage { router = inject(Router); - constructor() {} - - ngOnInit() {} - jumpTo(anchor: string) { const element = document.querySelector(`#${anchor}`); diff --git a/src/app/modals/confirm-attendance/confirm-attendance.routes.ts b/src/app/modals/confirm-attendance/confirm-attendance.routes.ts index 841c2866..f12908dd 100644 --- a/src/app/modals/confirm-attendance/confirm-attendance.routes.ts +++ b/src/app/modals/confirm-attendance/confirm-attendance.routes.ts @@ -1,4 +1,4 @@ -import { RouterModule, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { ConfirmAttendancePage } from './confirm-attendance'; export const routes: Routes = [ diff --git a/src/app/modals/confirm-attendance/confirm-attendance.ts b/src/app/modals/confirm-attendance/confirm-attendance.ts index 85ed4f2f..e2b8ab00 100644 --- a/src/app/modals/confirm-attendance/confirm-attendance.ts +++ b/src/app/modals/confirm-attendance/confirm-attendance.ts @@ -88,7 +88,7 @@ export class ConfirmAttendancePage { private afs: AngularFirestore, private navController: NavController, private router: Router, - private toastController: ToastController, + private toastController: ToastController ) { this.eventID = this.route.snapshot.params['eventID']; this.dataForm = this.formBuilder.group({ @@ -112,7 +112,7 @@ export class ConfirmAttendancePage { .pipe(map((doc) => doc.exists)); const evaluateBool = combineLatest([payingAttendance, nonPayingAttendance]).pipe( - map(([paying, nonPaying]) => paying || nonPaying), + map(([paying, nonPaying]) => paying || nonPaying) ); evaluateBool.subscribe((isAttendanceAlreadyCollected) => { @@ -191,7 +191,7 @@ export class ConfirmAttendancePage { ?.get('code') ?.valueChanges.pipe(untilDestroyed(this)) .subscribe((value) => { - if (value == this.attendanceCode) { + if (value === this.attendanceCode) { this.onSubmit(); } }); @@ -201,7 +201,7 @@ export class ConfirmAttendancePage { untilDestroyed(this), map((event) => ({ name: event?.name || 'Evento indefinido', - })), + })) ); } @@ -219,11 +219,11 @@ export class ConfirmAttendancePage { toast.present(); } - codeValidator = (formControl: AbstractControl): { [key: string]: boolean } | null => { + codeValidator = (formControl: AbstractControl): Record | null => { if (!this.attendanceCode) { return { codeLoading: true }; } - if (formControl.value == this.attendanceCode) { + if (formControl.value === this.attendanceCode) { return null; } else { return { wrongCode: true }; @@ -259,17 +259,15 @@ export class ConfirmAttendancePage { if (!subscriptionItem) { return; } - if (subscriptionItem['payment'].status == 2) { + if (subscriptionItem['payment'].status === 2) { // Escrevendo na coleção 'attendance' this.eventRef.collection('attendance').doc(userID).set({ - // @ts-ignore time: serverTimestamp(), author: 'online', }); } else { // Escrevendo na coleção 'non-paying-attendance' this.eventRef.collection('non-paying-attendance').doc(userID).set({ - // @ts-ignore time: serverTimestamp(), author: 'online', }); @@ -278,7 +276,6 @@ export class ConfirmAttendancePage { } else { // Escrevendo na coleção 'attendance' this.eventRef.collection('attendance').doc(userID).set({ - // @ts-ignore time: serverTimestamp(), author: 'online', }); @@ -287,7 +284,6 @@ export class ConfirmAttendancePage { this.afs .doc(`users/${userID}`) .update({ - // @ts-ignore 'pending.onlineAttendance': arrayRemove(this.eventID), }) .then(() => { diff --git a/src/app/profile/my-attendances/components/event-card-display-main-page/event-card-display-main-page.component.ts b/src/app/profile/my-attendances/components/event-card-display-main-page/event-card-display-main-page.component.ts index 5cff32f4..38f1bb5c 100644 --- a/src/app/profile/my-attendances/components/event-card-display-main-page/event-card-display-main-page.component.ts +++ b/src/app/profile/my-attendances/components/event-card-display-main-page/event-card-display-main-page.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { Observable } from 'rxjs'; import { EventSubscriptionLocal } from 'src/app/profile/my-attendances/my-attendances.page'; import { AsyncPipe } from '@angular/common'; @@ -35,10 +35,6 @@ import { EventCardComponent } from 'src/app/profile/my-attendances/components/ev EventCardComponent, ], }) -export class EventCardDisplayMainPageComponent implements OnInit { +export class EventCardDisplayMainPageComponent { @Input() eventSubscriptionsInput!: Observable; - - constructor() {} - - ngOnInit() {} } diff --git a/src/app/profile/my-attendances/components/event-card/event-card.component.ts b/src/app/profile/my-attendances/components/event-card/event-card.component.ts index 607510d2..e146e646 100644 --- a/src/app/profile/my-attendances/components/event-card/event-card.component.ts +++ b/src/app/profile/my-attendances/components/event-card/event-card.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { DateService } from 'src/app/shared/services/date.service'; import { EventSubscriptionLocal } from 'src/app/profile/my-attendances/my-attendances.page'; import { AsyncPipe, DatePipe } from '@angular/common'; @@ -38,10 +38,8 @@ import { RouterLink } from '@angular/router'; IonIcon, ], }) -export class EventCardComponent implements OnInit { +export class EventCardComponent { @Input() eventSubscription!: EventSubscriptionLocal; constructor(public dateService: DateService) {} - - ngOnInit() {} } diff --git a/src/app/profile/my-attendances/components/list-certificates/list-certificates.component.ts b/src/app/profile/my-attendances/components/list-certificates/list-certificates.component.ts index 556c6e32..a0b9c242 100644 --- a/src/app/profile/my-attendances/components/list-certificates/list-certificates.component.ts +++ b/src/app/profile/my-attendances/components/list-certificates/list-certificates.component.ts @@ -1,7 +1,7 @@ import { AsyncPipe } from '@angular/common'; import { CertificateStoreData } from 'src/app/shared/services/certificates.service'; import { MailtoService, Mailto } from 'src/app/shared/services/mailto.service'; -import { Component, inject, OnInit } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { ModalController, ToastController } from '@ionic/angular/standalone'; import { filterNullish } from 'src/app/shared/services/rxjs.service'; @@ -69,7 +69,7 @@ export class ListCertificatesComponent { private mailtoService: MailtoService, private certificateService: CertificateService, private toastController: ToastController, - private route: ActivatedRoute, + private route: ActivatedRoute ) { this.user$ = user(this.auth).pipe(filterNullish()); this.majorEventID = this.route.snapshot.paramMap.get('majorEventID') as string; @@ -81,7 +81,7 @@ export class ListCertificatesComponent { map((user) => { const colRef = collection( this.firestore, - `/users/${user.uid}/userCertificates/majorEvents/${this.majorEventID}`, + `/users/${user.uid}/userCertificates/majorEvents/${this.majorEventID}` ); const col$ = collectionData(colRef, { idField: 'id' }) as Observable; @@ -91,7 +91,7 @@ export class ListCertificatesComponent { certificates.map((certificate) => { const docRef = doc( this.firestore, - `/majorEvents/${this.majorEventID}/majorEventCertificates/${certificate.id}`, + `/majorEvents/${this.majorEventID}/majorEventCertificates/${certificate.id}` ); const docData$ = docData(docRef, { idField: 'id' }) as Observable; @@ -104,14 +104,14 @@ export class ListCertificatesComponent { ...(certificateData as CertificateStoreData), id: certificateData.id, }; - }), + }) ), }; - }), - ), + }) + ) ); }), - switchMap((value) => value), + switchMap((value) => value) ); } @@ -128,6 +128,7 @@ export class ListCertificatesComponent { this.mailtoService.open(mailto); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any async getCertificate(event: any, certificateData: CertificateStoreData, certificate: UserCertificateDocumentLocal) { event.target.disabled = true; diff --git a/src/app/profile/my-attendances/more-info/event-list/event-list.component.html b/src/app/profile/my-attendances/more-info/event-list/event-list.component.html index 3748cc0c..cfd8934f 100644 --- a/src/app/profile/my-attendances/more-info/event-list/event-list.component.html +++ b/src/app/profile/my-attendances/more-info/event-list/event-list.component.html @@ -1,32 +1,35 @@ -@if (eventInput | async; as eventsArray) { - @if (eventsArray.length === 0) { -

Você inscreveu-se em todos os eventos

- } - @for (event of eventsArray; track event; let i = $index) { - @if (i == 0 || !dateService.compareDayTimestamp(eventsArray[i - 1].eventStartDate, event.eventStartDate)) { - - - {{ formatDate(dateService.getDateFromTimestamp(event.eventStartDate)) }} - - - } - - - - -

{{ event.name }}

-

{{ event.shortDescription }}

-

- {{ dateService.getDateFromTimestamp(event.eventStartDate) | date: 'HH:mm' }} - {{ event.eventEndDate && ' às ' + (dateService.getDateFromTimestamp(event.eventEndDate) | date: 'HH:mm') }} -

- - - @if (isSubscribedList) {} -
-
-
- } -} @else { - +@if (eventInput | async; as eventsArray) { @if (eventsArray.length === 0) { +

Você inscreveu-se em todos os eventos

+} @for (event of eventsArray; track event; let i = $index) { @if (i===0 || +!dateService.compareDayTimestamp(eventsArray[i - 1].eventStartDate, event.eventStartDate)) { + + + {{ formatDate(dateService.getDateFromTimestamp(event.eventStartDate)) }} + + +} + + + + +

{{ event.name }}

+

{{ event.shortDescription }}

+

+ {{ dateService.getDateFromTimestamp(event.eventStartDate) | date : 'HH:mm' }} + {{ event.eventEndDate && ' às ' + (dateService.getDateFromTimestamp(event.eventEndDate) | date : 'HH:mm') }} +

+ + + @if (isSubscribedList) {} +
+
+
+} } @else { + } diff --git a/src/app/profile/my-attendances/more-info/event-list/event-list.component.ts b/src/app/profile/my-attendances/more-info/event-list/event-list.component.ts index 5a0e1357..60afb1c5 100644 --- a/src/app/profile/my-attendances/more-info/event-list/event-list.component.ts +++ b/src/app/profile/my-attendances/more-info/event-list/event-list.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { Observable } from 'rxjs'; import { EventItem } from 'src/app/shared/services/event'; @@ -27,13 +27,14 @@ import { RouterLink } from '@angular/router'; DatePipe, ], }) -export class EventListComponent implements OnInit { +export class EventListComponent { @Input() eventInput!: Observable; @Input() isSubscribedList!: boolean; - constructor(public emojiService: EmojiService, public dateService: DateService) {} - - ngOnInit() {} + constructor( + public emojiService: EmojiService, + public dateService: DateService, + ) {} formatDate(date: Date): string { let formated = formatDate(date, "EEEE, dd 'de' MMMM 'de' yyyy", 'pt-BR'); diff --git a/src/app/profile/my-attendances/more-info/more-info.page.html b/src/app/profile/my-attendances/more-info/more-info.page.html index 0e7af8b3..a73511ad 100644 --- a/src/app/profile/my-attendances/more-info/more-info.page.html +++ b/src/app/profile/my-attendances/more-info/more-info.page.html @@ -10,8 +10,8 @@ @if (majorEvent$ | async; as majorEvent) { @if (majorEventSubscription$ | async; as majorEventSubscription) {
- - + + @if (majorEvent.price) {
diff --git a/src/app/profile/my-attendances/more-info/more-info.page.ts b/src/app/profile/my-attendances/more-info/more-info.page.ts index 5ab8fd6d..38b4fe40 100644 --- a/src/app/profile/my-attendances/more-info/more-info.page.ts +++ b/src/app/profile/my-attendances/more-info/more-info.page.ts @@ -34,8 +34,8 @@ import { IonSpinner, ModalController, } from '@ionic/angular/standalone'; -import { HeaderComponent } from 'src/app/shared/components/major-event-display/header/header.component'; -import { DescriptionComponent } from 'src/app/shared/components/major-event-display/description/description.component'; +import { MajorEventHeaderComponent } from 'src/app/shared/components/major-event-display/major-event-header/major-event-header.component'; +import { MajorEventDescriptionComponent } from 'src/app/shared/components/major-event-display/major-event-description/major-event-description.component'; import { DateComponent } from 'src/app/shared/components/major-event-display/date/date.component'; import { EventListComponent } from 'src/app/profile/my-attendances/more-info/event-list/event-list.component'; @@ -61,8 +61,8 @@ import { EventListComponent } from 'src/app/profile/my-attendances/more-info/eve IonAccordion, IonProgressBar, IonSpinner, - HeaderComponent, - DescriptionComponent, + MajorEventDescriptionComponent, + MajorEventHeaderComponent, DateComponent, EventListComponent, DatePipe, @@ -111,7 +111,7 @@ export class MoreInfoPage implements OnInit { .pipe(trace('firestore'), take(1)) .subscribe((document) => { const data = document.data() as MajorEventSubscription; - const subscribedEventsObservables: Array> = []; + const subscribedEventsObservables: Observable[] = []; for (let i = 0; i < data.subscribedToEvents.length; i += 10) { subscribedEventsObservables.push( this.afs @@ -130,7 +130,7 @@ export class MoreInfoPage implements OnInit { }), ); - const notSubscribedEventsObservables: Array> = []; + const notSubscribedEventsObservables: Observable[] = []; for (let i = 0; i < data.subscribedToEvents.length; i += 10) { notSubscribedEventsObservables.push( this.afs diff --git a/src/app/profile/my-attendances/more-info/more-info.routes.ts b/src/app/profile/my-attendances/more-info/more-info.routes.ts index eb8941b1..db21e0ae 100644 --- a/src/app/profile/my-attendances/more-info/more-info.routes.ts +++ b/src/app/profile/my-attendances/more-info/more-info.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { MoreInfoPage } from './more-info.page'; diff --git a/src/app/profile/my-attendances/my-attendances.page.ts b/src/app/profile/my-attendances/my-attendances.page.ts index 1062ecee..5c73ac8b 100644 --- a/src/app/profile/my-attendances/my-attendances.page.ts +++ b/src/app/profile/my-attendances/my-attendances.page.ts @@ -1,6 +1,6 @@ import { EventItem, EventSubscription } from 'src/app/shared/services/event'; import { MajorEventItem, MajorEventSubscription } from '../../shared/services/major-event.service'; -import { Component, inject, OnInit } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { map, Observable, switchMap, combineLatest, shareReplay, catchError } from 'rxjs'; import { @@ -81,7 +81,7 @@ import { EventCardDisplayMainPageComponent } from 'src/app/profile/my-attendance NgTemplateOutlet, ], }) -export class MyAttendancesPage implements OnInit { +export class MyAttendancesPage { private auth: Auth = inject(Auth); user$ = user(this.auth).pipe(shareReplay(1), untilDestroyed(this)); @@ -92,10 +92,7 @@ export class MyAttendancesPage implements OnInit { today: Date = new Date(); - constructor( - public enrollmentTypes: EnrollmentTypesService, - public dateService: DateService, - ) { + constructor(public enrollmentTypes: EnrollmentTypesService, public dateService: DateService) { this.subscriptions$ = this.user$.pipe( switchMap((user) => { if (!user) { @@ -109,16 +106,16 @@ export class MyAttendancesPage implements OnInit { return { id: subscription.id, userData: docData( - doc(this.firestore, `majorEvents/${subscription.id}/subscriptions/${user.uid}`), + doc(this.firestore, `majorEvents/${subscription.id}/subscriptions/${user.uid}`) ) as Observable, majorEvent: docData(doc(this.firestore, `majorEvents/${subscription.id}`), { idField: 'id', }) as Observable, }; }); - }), + }) ); - }), + }) ); this.eventSubscriptions$ = this.user$.pipe( @@ -148,29 +145,27 @@ export class MyAttendancesPage implements OnInit { id: event.id, event: event, userData: userData as EventSubscription, - })), + })) ); }); return combineLatest(eventsWithUserData).pipe( map((eventsWithUserData) => { return eventsWithUserData; - }), + }) ); - }), + }) ); }), catchError((error) => { console.error('Error fetching data:', error); return []; - }), + }) ); - }), + }) ); } - ngOnInit() {} - isInSubscriptionPeriod(endDateTimestamp: Timestamp): boolean { if (endDateTimestamp) { const endDate = this.dateService.getDateFromTimestamp(endDateTimestamp); @@ -203,6 +198,7 @@ interface Subscription { export interface EventSubscriptionLocal { id?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any reference?: DocumentReference; userData?: EventSubscription; event?: EventItem; diff --git a/src/app/profile/my-attendances/my-attendances.routes.ts b/src/app/profile/my-attendances/my-attendances.routes.ts index 1c0dea7b..a9ecb429 100644 --- a/src/app/profile/my-attendances/my-attendances.routes.ts +++ b/src/app/profile/my-attendances/my-attendances.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { MyAttendancesPage } from './my-attendances.page'; diff --git a/src/app/profile/my-attendances/send-receipt/send-receipt.page.html b/src/app/profile/my-attendances/send-receipt/send-receipt.page.html index 32f6203b..b600eeff 100644 --- a/src/app/profile/my-attendances/send-receipt/send-receipt.page.html +++ b/src/app/profile/my-attendances/send-receipt/send-receipt.page.html @@ -105,7 +105,7 @@

Dados para o pagamento

Comprovante enviado

@if (downloadURL) { - + Comprovante enviado }
} diff --git a/src/app/profile/my-attendances/send-receipt/send-receipt.page.ts b/src/app/profile/my-attendances/send-receipt/send-receipt.page.ts index fb817f9b..aaa6b336 100644 --- a/src/app/profile/my-attendances/send-receipt/send-receipt.page.ts +++ b/src/app/profile/my-attendances/send-receipt/send-receipt.page.ts @@ -3,14 +3,13 @@ import { Component, inject, OnInit, ViewChild } from '@angular/core'; import { Storage, ref, uploadBytesResumable, getDownloadURL } from '@angular/fire/storage'; import { Observable } from 'rxjs'; -import { finalize, take } from 'rxjs/operators'; +import { take } from 'rxjs/operators'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { NgxImageCompressService } from 'ngx-image-compress'; import { ToastController } from '@ionic/angular/standalone'; import { ActivatedRoute, Router } from '@angular/router'; import { AngularFirestore, DocumentReference } from '@angular/fire/compat/firestore'; import { trace } from '@angular/fire/compat/performance'; -import { fromUnixTime } from 'date-fns'; import { MajorEventItem } from 'src/app/shared/services/major-event.service'; import { Timestamp } from '@firebase/firestore'; @@ -102,7 +101,7 @@ export class SendReceiptPage implements OnInit { rawFile: string; userSubscription$: Promise; today: Date = new Date(); - outOfDate: boolean = false; + outOfDate = false; constructor( private imageCompress: NgxImageCompressService, @@ -235,6 +234,7 @@ export class SendReceiptPage implements OnInit { ); } + // eslint-disable-next-line @typescript-eslint/no-unused-vars uploadFile(result: string, format: string) { // Attribution: Harsh Mittal // https://stackoverflow.com/questions/68324916/resize-compress-selected-image-before-uploading-to-firebase-in-angular @@ -282,6 +282,7 @@ export class SendReceiptPage implements OnInit { updateUser() { this.afs + // eslint-disable-next-line @typescript-eslint/no-explicit-any .doc(`/majorEvents/${this.eventID}/subscriptions/${this.uid}`) .update({ 'payment.status': 1, @@ -374,6 +375,7 @@ export class SendReceiptPage implements OnInit { interface Subscription { id?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any reference?: DocumentReference; } diff --git a/src/app/profile/my-attendances/send-receipt/send-receipt.routes.ts b/src/app/profile/my-attendances/send-receipt/send-receipt.routes.ts index 2897cef9..0a713d8f 100644 --- a/src/app/profile/my-attendances/send-receipt/send-receipt.routes.ts +++ b/src/app/profile/my-attendances/send-receipt/send-receipt.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { SendReceiptPage } from './send-receipt.page'; diff --git a/src/app/profile/profile-info.page.ts b/src/app/profile/profile-info.page.ts index 462df242..b252b8dd 100644 --- a/src/app/profile/profile-info.page.ts +++ b/src/app/profile/profile-info.page.ts @@ -70,8 +70,8 @@ export class ProfileInfoPage implements OnInit { private router: Router, ) {} - alreadyLinked: boolean = false; - isUnesp: boolean = false; + alreadyLinked = false; + isUnesp = false; userData: User; ngOnInit() { diff --git a/src/app/profile/profile-info.routes.ts b/src/app/profile/profile-info.routes.ts index 7ba63b4a..c32aee57 100644 --- a/src/app/profile/profile-info.routes.ts +++ b/src/app/profile/profile-info.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { ProfileInfoPage } from './profile-info.page'; diff --git a/src/app/profile/register/register.page.html b/src/app/profile/register/register.page.html index 14718073..4f7b5e2c 100644 --- a/src/app/profile/register/register.page.html +++ b/src/app/profile/register/register.page.html @@ -112,12 +112,14 @@

Se você está tendo problemas com a sua inscrição, - entre em contato com o CACiC. + entre em contato com o CACiC.

Se você não possui CPF ou um número de celular brasileiro, - entre em contato com o CACiC. + entre em contato com o CACiC.

diff --git a/src/app/profile/register/register.page.ts b/src/app/profile/register/register.page.ts index b920807a..fb83dd04 100644 --- a/src/app/profile/register/register.page.ts +++ b/src/app/profile/register/register.page.ts @@ -71,15 +71,17 @@ import { WindowService } from '../../shared/services/window.service'; export class RegisterPage implements OnInit { @ViewChild('mySwal') private mySwal: SwalComponent; + // eslint-disable-next-line @typescript-eslint/no-explicit-any windowRef: any; private auth: Auth = inject(Auth); dataVersion: string = GlobalConstantsService.userDataVersion; + // eslint-disable-next-line @typescript-eslint/no-explicit-any userData: any; dataForm: FormGroup; - isUnesp: boolean = false; - isUndergraduate: boolean = false; + isUnesp = false; + isUndergraduate = false; constructor( public authService: AuthService, @@ -89,7 +91,7 @@ export class RegisterPage implements OnInit { public router: Router, private mailtoService: MailtoService, private win: WindowService, - private toastController: ToastController, + private toastController: ToastController ) { this.userData = JSON.parse(localStorage.getItem('user')); @@ -279,17 +281,17 @@ export class RegisterPage implements OnInit { return false; } - let sum: number = 0; + let sum = 0; let rest: number; for (let i = 1; i <= 9; i++) sum = sum + parseInt(cpf.substring(i - 1, i)) * (11 - i); rest = (sum * 10) % 11; - if (rest == 10 || rest == 11) rest = 0; - if (rest != parseInt(cpf.substring(9, 10))) return false; + if (rest === 10 || rest === 11) rest = 0; + if (rest !== parseInt(cpf.substring(9, 10))) return false; sum = 0; for (let i = 1; i <= 10; i++) sum = sum + parseInt(cpf.substring(i - 1, i)) * (12 - i); rest = (sum * 10) % 11; - if (rest == 10 || rest == 11) rest = 0; - if (rest != parseInt(cpf.substring(10, 11))) return false; + if (rest === 10 || rest === 11) rest = 0; + if (rest !== parseInt(cpf.substring(10, 11))) return false; return true; } diff --git a/src/app/profile/register/register.routes.ts b/src/app/profile/register/register.routes.ts index e7867fa7..5ba701c9 100644 --- a/src/app/profile/register/register.routes.ts +++ b/src/app/profile/register/register.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { RegisterPage } from './register.page'; diff --git a/src/app/profile/wallet/wallet.page.html b/src/app/profile/wallet/wallet.page.html index 3b064ed7..1d670b5e 100644 --- a/src/app/profile/wallet/wallet.page.html +++ b/src/app/profile/wallet/wallet.page.html @@ -15,7 +15,7 @@ @if (userFirestore$ | async; as userFirestore) {
- + Avatar do usuário

{{ (userFirestore$ | async)?.fullName || user.displayName }}

@@ -32,7 +32,11 @@

{{ (userFirestore$ | async)?.fullName || user

- + + @if (serviceWorkerActive) {
@@ -97,7 +101,7 @@

Cartão do RU

- + Avatar do usuário

{{ (userFirestore$ | async)?.fullName || user.displayName }}

@@ -110,7 +114,7 @@

123321

- + } } diff --git a/src/app/profile/wallet/wallet.page.ts b/src/app/profile/wallet/wallet.page.ts index dc74b246..f7b115eb 100644 --- a/src/app/profile/wallet/wallet.page.ts +++ b/src/app/profile/wallet/wallet.page.ts @@ -1,5 +1,5 @@ import { AngularFirestore } from '@angular/fire/compat/firestore'; -import { Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit } from '@angular/core'; +import { Component, CUSTOM_ELEMENTS_SCHEMA, inject } from '@angular/core'; import { Auth, user, getIdTokenResult } from '@angular/fire/auth'; import { CoursesService } from 'src/app/shared/services/courses.service'; @@ -8,7 +8,11 @@ import { User } from 'src/app/shared/services/user'; import { trace } from '@angular/fire/compat/performance'; import { AsyncPipe } from '@angular/common'; -import { azteccode, interleaved2of5, drawingSVG } from 'bwip-js'; +import { + azteccode, + //interleaved2of5, + drawingSVG, +} from 'bwip-js'; import { SafePipe } from 'src/app/shared/pipes/safe.pipe'; @@ -62,7 +66,7 @@ import { filterNullish } from 'src/app/shared/services/rxjs.service'; AsyncPipe, ], }) -export class WalletPage implements OnInit { +export class WalletPage { public profileBarcode: string | undefined; // public restaurantBarcode: string; @@ -71,15 +75,11 @@ export class WalletPage implements OnInit { user$: Observable = user(this.auth); userFirestore$: Observable | undefined; academicID$: Observable | undefined; - public serviceWorkerActive: boolean = false; + public serviceWorkerActive = false; _isProfessor = new BehaviorSubject(false); isProfessor$: Observable = this._isProfessor.asObservable(); - constructor( - public courses: CoursesService, - private afs: AngularFirestore, - private sw: ServiceWorkerService, - ) { + constructor(public courses: CoursesService, private afs: AngularFirestore, private sw: ServiceWorkerService) { this.serviceWorkerActive = this.sw.getServiceWorkerStatus(); this.user$.pipe(filterNullish(), take(1), trace('auth')).subscribe((user: AuthUser) => { @@ -96,7 +96,7 @@ export class WalletPage implements OnInit { .pipe( take(1), trace('firestore'), - filter((user): user is User => user !== undefined), + filter((user): user is User => user !== undefined) ); this.renderAztecCode(user.uid); @@ -104,8 +104,8 @@ export class WalletPage implements OnInit { }); } - ngOnInit() { - /* registerSwiper(); + // ngOnInit() { + /* registerSwiper(); const swiperEl = document.querySelector('swiper-container'); const swiperParams: SwiperOptions = { @@ -136,22 +136,22 @@ export class WalletPage implements OnInit { swiperEl.initialize(); this.render2DBarcode('123321');*/ - } + // } renderAztecCode(uid: string) { try { - let svg: string = String( + const svg = String( azteccode( { bcid: 'interleaved2of5', text: `uid:${uid}`, scale: 3, includetext: false, - // @ts-ignore - Required since eclevel actually exists + // @ts-expect-error - Required since eclevel actually exists eclevel: '23', }, - drawingSVG(), - ), + drawingSVG() + ) ); this.profileBarcode = svg; diff --git a/src/app/restricted-area/manage-admins/manage-admins.page.ts b/src/app/restricted-area/manage-admins/manage-admins.page.ts index 2b794603..bcbede85 100644 --- a/src/app/restricted-area/manage-admins/manage-admins.page.ts +++ b/src/app/restricted-area/manage-admins/manage-admins.page.ts @@ -1,4 +1,4 @@ -import { Component, inject, OnInit } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { Functions, httpsCallable } from '@angular/fire/functions'; @@ -52,7 +52,7 @@ import { AsyncPipe } from '@angular/common'; AsyncPipe, ], }) -export class ManageAdminsPage implements OnInit { +export class ManageAdminsPage { private firestore: Firestore = inject(Firestore); private functions: Functions = inject(Functions); @@ -63,13 +63,11 @@ export class ManageAdminsPage implements OnInit { }); constructor(public toastController: ToastController, private alertController: AlertController) { - this.adminList$ = docData(doc(this.firestore, 'claims', 'admin')).pipe(map((doc) => doc['admins'])) as Observable< - string[] - >; + this.adminList$ = docData(doc(this.firestore, 'claims', 'admin')).pipe( + map((doc) => (doc ? doc['admins'] : [])) + ) as Observable; } - ngOnInit() {} - async errorToast(message: string) { const toast = await this.toastController.create({ message: message, @@ -89,7 +87,7 @@ export class ManageAdminsPage implements OnInit { addAdmin() { const addAdminRole = httpsCallable(this.functions, 'claims-addAdminRole'); addAdminRole({ email: this.addAdminForm.value.adminEmail }) - .then((res) => { + .then(() => { this.successToast(); this.addAdminForm.reset(); }) @@ -102,7 +100,7 @@ export class ManageAdminsPage implements OnInit { removeAdmin(adminEmail: string) { const removeAdminRole = httpsCallable(this.functions, 'claims-removeAdminRole'); removeAdminRole({ email: adminEmail }) - .then((res) => { + .then(() => { this.successToast(); }) .catch((err) => { @@ -114,7 +112,7 @@ export class ManageAdminsPage implements OnInit { certificateMove() { const moveCertificates = httpsCallable(this.functions, 'moveCertificates-moveCertificates'); moveCertificates() - .then((res) => { + .then(() => { this.successToast(); }) .catch((err) => { diff --git a/src/app/restricted-area/manage-admins/manage-admins.routes.ts b/src/app/restricted-area/manage-admins/manage-admins.routes.ts index 9f4c7177..1abbbcd6 100644 --- a/src/app/restricted-area/manage-admins/manage-admins.routes.ts +++ b/src/app/restricted-area/manage-admins/manage-admins.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { ManageAdminsPage } from './manage-admins.page'; diff --git a/src/app/restricted-area/manage-events/add-event/add-event.page.ts b/src/app/restricted-area/manage-events/add-event/add-event.page.ts index 456a27d8..11f4be55 100644 --- a/src/app/restricted-area/manage-events/add-event/add-event.page.ts +++ b/src/app/restricted-area/manage-events/add-event/add-event.page.ts @@ -14,13 +14,11 @@ import { format, getDayOfYear, isEqual, parseISO, setDayOfYear, subMilliseconds import { AngularFirestore } from '@angular/fire/compat/firestore'; import { Router } from '@angular/router'; import { take, Observable, map } from 'rxjs'; -import { Timestamp, arrayUnion } from '@firebase/firestore'; import { EventItem } from 'src/app/shared/services/event'; -import { Timestamp as TimestampType } from '@firebase/firestore-types'; import { SwalComponent, SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2'; -import { ConfirmModalPage } from './confirm-modal/confirm-modal.page'; +import { ConfirmAddEventModalPage } from './confirm-add-event-modal/confirm-add-event-modal.page'; import { getStringChanges, RemoteConfig } from '@angular/fire/remote-config'; -import { serverTimestamp } from '@angular/fire/firestore'; +import { serverTimestamp, Timestamp, arrayUnion } from '@angular/fire/firestore'; import { Auth, user } from '@angular/fire/auth'; import { IonSelect, @@ -89,10 +87,11 @@ export class AddEventPage implements OnInit { courses = CoursesService.courses; majorEventsData$: Observable; - hasDateEnd: boolean = false; + hasDateEnd = false; dataForm: FormGroup; + // eslint-disable-next-line @typescript-eslint/no-explicit-any userData: any; places$: Observable; @@ -107,7 +106,7 @@ export class AddEventPage implements OnInit { private modalController: ModalController, public majorEvents: MajorEventsService, private afs: AngularFirestore, - private router: Router, + private router: Router ) { this.userData = JSON.parse(localStorage.getItem('user')); } @@ -156,7 +155,7 @@ export class AddEventPage implements OnInit { }, { validators: [this.validatorLatLong, this.validatorButton, this.validatorDateEnd], - }, + } ); this.userData.displayName.replace(/%20/g, ' '); this.majorEventsData$ = this.majorEvents.getCurrentAndFutureMajorEvents(); @@ -169,7 +168,7 @@ export class AddEventPage implements OnInit { return parsed; } return {}; - }), + }) ); } @@ -189,7 +188,7 @@ export class AddEventPage implements OnInit { majorEvent = null; } - let dateEnd: TimestampType | null; + let dateEnd: Timestamp | null; if (this.hasDateEnd) { dateEnd = Timestamp.fromDate(new Date(this.dataForm.get('eventEndDate').value)); @@ -197,7 +196,7 @@ export class AddEventPage implements OnInit { dateEnd = null; } - let buttonUrl: string = this.dataForm.get('button').get('url').value; + const buttonUrl: string = this.dataForm.get('button').get('url').value; if (buttonUrl) { const pattern = /^((http|https):\/\/)/; @@ -209,7 +208,7 @@ export class AddEventPage implements OnInit { } } - let location: { description: any; lat: any; lon: any } | null; + let location: { description: string; lat: number; lon: number } | null; if ( !this.dataForm.get('location.description').value && @@ -220,8 +219,8 @@ export class AddEventPage implements OnInit { } else { location = { description: this.dataForm.get('location.description').value, - lat: this.dataForm.get('location.lat').value || null, - lon: this.dataForm.get('location.lon').value || null, + lat: Number.parseInt(this.dataForm.get('location.lat').value) || null, + lon: Number.parseInt(this.dataForm.get('location.lon').value) || null, }; } @@ -250,7 +249,7 @@ export class AddEventPage implements OnInit { collectAttendance: this.dataForm.get('collectAttendance').value, creditHours: Number.parseInt(this.dataForm.get('creditHours').value) || null, createdBy: user.uid, - // @ts-ignore + // @ts-expect-error - This works createdOn: serverTimestamp(), slotsAvailable: Number.parseInt(this.dataForm.get('slotsAvailable').value) || 0, numberOfSubscriptions: 0, @@ -297,7 +296,7 @@ export class AddEventPage implements OnInit { async openConfirmModal(): Promise { const modal = await this.modalController.create({ - component: ConfirmModalPage, + component: ConfirmAddEventModalPage, componentProps: { dataForm: this.dataForm, hasDateEnd: this.hasDateEnd, @@ -339,7 +338,7 @@ export class AddEventPage implements OnInit { return null; } - validatorDateEnd(control: AbstractControl): { [key: string]: boolean } | null { + validatorDateEnd(control: AbstractControl): Record | null { if (control.get('hasDateEndForm').value) { const dateStart = parseISO(control.get('eventStartDate').value); const dateEnd = parseISO(control.get('eventEndDate').value); @@ -359,6 +358,7 @@ export class AddEventPage implements OnInit { return null; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any placeChange(ev: any) { if (this.parsedPlaces[ev.detail.value] === undefined) { return 1; @@ -369,9 +369,7 @@ export class AddEventPage implements OnInit { .get('description') .setValue( this.parsedPlaces[ev.detail.value].name + - (this.parsedPlaces[ev.detail.value].description - ? ' - ' + this.parsedPlaces[ev.detail.value].description - : ''), + (this.parsedPlaces[ev.detail.value].description ? ' - ' + this.parsedPlaces[ev.detail.value].description : '') ); this.dataForm.get('location').get('lat').setValue(this.parsedPlaces[ev.detail.value].lat); this.dataForm.get('location').get('lon').setValue(this.parsedPlaces[ev.detail.value].lon); @@ -389,17 +387,18 @@ export class AddEventPage implements OnInit { onDateStartChange() { const newTime = setDayOfYear( parseISO(this.dataForm.get('eventEndDate').value), - getDayOfYear(parseISO(this.dataForm.get('eventStartDate').value)), + getDayOfYear(parseISO(this.dataForm.get('eventStartDate').value)) ); this.dataForm.get('eventEndDate').setValue(subMilliseconds(newTime, this.tzoffset).toISOString().slice(0, -1)); } } -interface placesRemoteConfig { - [key: string]: { +type placesRemoteConfig = Record< + string, + { name: string; description: string; lat: string; lon: string; - }; -} + } +>; diff --git a/src/app/restricted-area/manage-events/add-event/add-event.routes.ts b/src/app/restricted-area/manage-events/add-event/add-event.routes.ts index 9bdb9f15..1ccd1f62 100644 --- a/src/app/restricted-area/manage-events/add-event/add-event.routes.ts +++ b/src/app/restricted-area/manage-events/add-event/add-event.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { AddEventPage } from './add-event.page'; export const routes: Routes = [ diff --git a/src/app/restricted-area/manage-events/add-event/confirm-modal/confirm-modal.page.html b/src/app/restricted-area/manage-events/add-event/confirm-add-event-modal/confirm-add-event-modal.page.html similarity index 95% rename from src/app/restricted-area/manage-events/add-event/confirm-modal/confirm-modal.page.html rename to src/app/restricted-area/manage-events/add-event/confirm-add-event-modal/confirm-add-event-modal.page.html index ef592b39..268ef89c 100644 --- a/src/app/restricted-area/manage-events/add-event/confirm-modal/confirm-modal.page.html +++ b/src/app/restricted-area/manage-events/add-event/confirm-add-event-modal/confirm-add-event-modal.page.html @@ -4,7 +4,10 @@
- + Emoji do evento

{{ dataForm.value.name }}

diff --git a/src/app/restricted-area/manage-events/add-event/confirm-modal/confirm-modal.page.scss b/src/app/restricted-area/manage-events/add-event/confirm-add-event-modal/confirm-add-event-modal.page.scss similarity index 100% rename from src/app/restricted-area/manage-events/add-event/confirm-modal/confirm-modal.page.scss rename to src/app/restricted-area/manage-events/add-event/confirm-add-event-modal/confirm-add-event-modal.page.scss diff --git a/src/app/restricted-area/manage-events/add-event/confirm-modal/confirm-modal.page.ts b/src/app/restricted-area/manage-events/add-event/confirm-add-event-modal/confirm-add-event-modal.page.ts similarity index 82% rename from src/app/restricted-area/manage-events/add-event/confirm-modal/confirm-modal.page.ts rename to src/app/restricted-area/manage-events/add-event/confirm-add-event-modal/confirm-add-event-modal.page.ts index 9403eb19..501fe31e 100644 --- a/src/app/restricted-area/manage-events/add-event/confirm-modal/confirm-modal.page.ts +++ b/src/app/restricted-area/manage-events/add-event/confirm-add-event-modal/confirm-add-event-modal.page.ts @@ -1,6 +1,6 @@ // @ts-strict-ignore import { FormGroup } from '@angular/forms'; -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { CoursesService } from 'src/app/shared/services/courses.service'; import { ModalController } from '@ionic/angular/standalone'; import { EmojiService } from '../../../../shared/services/emoji.service'; @@ -13,12 +13,14 @@ import { DatePipe } from '@angular/common'; @Component({ selector: 'app-confirm-modal', - templateUrl: './confirm-modal.page.html', - styleUrls: ['./confirm-modal.page.scss'], + templateUrl: './confirm-add-event-modal.page.html', + styleUrls: ['./confirm-add-event-modal.page.scss'], standalone: true, imports: [IonContent, IonItem, IonIcon, IonLabel, IonButton, IonGrid, IonRow, IonCol, SafePipe, DatePipe], }) -export class ConfirmModalPage implements OnInit { +export class ConfirmAddEventModalPage { + // TODO: Review any + // eslint-disable-next-line @typescript-eslint/no-explicit-any @Input() dataForm: FormGroup; @Input() hasDateEnd: boolean; @@ -30,8 +32,6 @@ export class ConfirmModalPage implements OnInit { public dateService: DateService ) {} - ngOnInit() {} - onSubmit() { this.modalController.dismiss(true); return; diff --git a/src/app/restricted-area/manage-events/attendance-scanner/scanner.page.ts b/src/app/restricted-area/manage-events/attendance-scanner/scanner.page.ts index f00b9555..5b7645de 100644 --- a/src/app/restricted-area/manage-events/attendance-scanner/scanner.page.ts +++ b/src/app/restricted-area/manage-events/attendance-scanner/scanner.page.ts @@ -38,7 +38,7 @@ import { IonFooter, } from '@ionic/angular/standalone'; -import { ScannerVideoComponent } from '../../../shared/components/aztec-scanner/aztec-scanner.component'; +import { AztecScannerComponent } from '../../../shared/components/aztec-scanner/aztec-scanner.component'; interface Attendance { user: Observable; @@ -74,13 +74,13 @@ interface Attendance { IonText, IonProgressBar, IonFooter, - ScannerVideoComponent -], + AztecScannerComponent, + ], }) export class ScannerPage implements OnInit { - @Input('manualInput') manualInput!: string; - @ViewChild('mySwal') mySwal: SwalComponent; - @ViewChild('scannerCanvas') scannerCanvas: HTMLCanvasElement; + @Input() manualInput!: string; + @ViewChild('mySwal') mySwal!: SwalComponent; + @ViewChild('scannerCanvas') scannerCanvas!: HTMLCanvasElement; private auth: Auth = inject(Auth); user$ = user(this.auth); @@ -88,9 +88,9 @@ export class ScannerPage implements OnInit { // QR Code scanner availableDevices!: MediaDeviceInfo[]; currentDevice: MediaDeviceInfo | null = null; - hasDevices: boolean = false; - hasPermission: boolean = false; - deviceIndex: number = -1; + hasDevices = false; + hasPermission = false; + deviceIndex = -1; attendanceCollection$: Observable; /** @@ -98,7 +98,7 @@ export class ScannerPage implements OnInit { */ nonPayingAttendanceCollection$: Observable; eventID: string; - event$: Observable; + event$: Observable; /** * Variable initialized at this.checkIfEventIsPaid(); * Variável inicializada no método this.checkIfEventIsPaid() @@ -113,7 +113,7 @@ export class ScannerPage implements OnInit { _backdropVisibleSubject: BehaviorSubject = new BehaviorSubject(false); backdropVisible$: Observable = this._backdropVisibleSubject.asObservable(); - attendanceSessionScans: number = 0; + attendanceSessionScans = 0; audioSuccess: HTMLAudioElement; audioDuplicate: HTMLAudioElement; @@ -129,7 +129,7 @@ export class ScannerPage implements OnInit { public courses: CoursesService, private toastController: ToastController, private authService: AuthService, - public dateService: DateService, + public dateService: DateService ) { this.eventID = this.route.snapshot.params['eventID']; @@ -153,12 +153,7 @@ export class ScannerPage implements OnInit { } }); - this.event$ = this.afs - .collection('events') - .doc(this.eventID) - .valueChanges() - // @ts-ignore - .pipe(trace('firestore')); + this.event$ = this.afs.collection('events').doc(this.eventID).valueChanges(); this.checkIfEventIsPaid(); // Get attendance list @@ -180,8 +175,8 @@ export class ScannerPage implements OnInit { .doc(item.id) .get() .pipe(map((document) => document.data())), - })), - ), + })) + ) ); // Get non-paying-attendance list @@ -204,8 +199,8 @@ export class ScannerPage implements OnInit { .doc(item.id) .get() .pipe(map((document) => document.data())), - })), - ), + })) + ) ); this.audioSuccess = new Audio(); @@ -271,7 +266,7 @@ export class ScannerPage implements OnInit { // Verify if event is a part of majorEvent const majorEventID = event.data()?.inMajorEvent; this.majorEventID = majorEventID; - const isSubEvent = majorEventID != null; + const isSubEvent = majorEventID !== null; // If it is a subEvent, check if majorEvent is paid if (isSubEvent) { this.afs @@ -304,7 +299,7 @@ export class ScannerPage implements OnInit { .pipe( take(1), trace('firestore'), - map((userDocument) => userDocument.exists), + map((userDocument) => userDocument.exists) ); } @@ -313,21 +308,24 @@ export class ScannerPage implements OnInit { * @param uid User ID, ID do usuário */ userPaid$(uid: string): Observable { - return this.afs - .collection(`majorEvents/${this.majorEventID}/subscriptions`) - .doc(uid) - .valueChanges() - .pipe( - untilDestroyed(this), - trace('firestore'), - map((subscription) => { - if (subscription) { - return subscription.payment.status == 2; - } else { - return false; - } - }), - ); + return ( + this.afs + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .collection(`majorEvents/${this.majorEventID}/subscriptions`) + .doc(uid) + .valueChanges() + .pipe( + untilDestroyed(this), + trace('firestore'), + map((subscription) => { + if (subscription) { + return subscription.payment.status === 2; + } else { + return false; + } + }) + ) + ); } /** @@ -405,7 +403,6 @@ export class ScannerPage implements OnInit { return false; } this.afs.collection(`events/${this.eventID}/attendance`).doc(uid).set({ - // @ts-ignore time: serverTimestamp(), author: this.adminID, }); @@ -436,7 +433,6 @@ export class ScannerPage implements OnInit { return false; } this.afs.collection(`events/${this.eventID}/non-paying-attendance`).doc(uid).set({ - // @ts-ignore time: serverTimestamp(), author: this.adminID, }); diff --git a/src/app/restricted-area/manage-events/attendance-scanner/scanner.routes.ts b/src/app/restricted-area/manage-events/attendance-scanner/scanner.routes.ts index 2c2192c9..d7764cfd 100644 --- a/src/app/restricted-area/manage-events/attendance-scanner/scanner.routes.ts +++ b/src/app/restricted-area/manage-events/attendance-scanner/scanner.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { ScannerPage } from './scanner.page'; diff --git a/src/app/restricted-area/manage-events/components/group-creation-modal/group-creation-modal.component.html b/src/app/restricted-area/manage-events/components/group-creation-modal/group-creation-modal.component.html index ac68d3a1..34d276b2 100644 --- a/src/app/restricted-area/manage-events/components/group-creation-modal/group-creation-modal.component.html +++ b/src/app/restricted-area/manage-events/components/group-creation-modal/group-creation-modal.component.html @@ -23,7 +23,13 @@ @for (event of eventGroup; track event; let i = $index) { - + diff --git a/src/app/restricted-area/manage-events/components/group-creation-modal/group-creation-modal.component.ts b/src/app/restricted-area/manage-events/components/group-creation-modal/group-creation-modal.component.ts index 0ad793a5..c85b5527 100644 --- a/src/app/restricted-area/manage-events/components/group-creation-modal/group-creation-modal.component.ts +++ b/src/app/restricted-area/manage-events/components/group-creation-modal/group-creation-modal.component.ts @@ -50,13 +50,13 @@ import { DatePipe } from '@angular/common'; ], }) export class GroupCreationModalComponent implements OnInit { - @Input() eventGroup!: Array<{ + @Input() eventGroup!: { id: string; name: string; icon: string; eventStartDate: Timestamp; eventEndDate: Timestamp; - }>; + }[]; dataForm: FormGroup; diff --git a/src/app/restricted-area/manage-events/list-attendances/list.page.ts b/src/app/restricted-area/manage-events/list-attendances/list.page.ts index 04bd127c..cadae500 100644 --- a/src/app/restricted-area/manage-events/list-attendances/list.page.ts +++ b/src/app/restricted-area/manage-events/list-attendances/list.page.ts @@ -1,5 +1,5 @@ import { ToastController, AlertController } from '@ionic/angular/standalone'; -import { Component, OnInit, ViewChild } from '@angular/core'; +import { Component, ViewChild } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { AngularFirestore } from '@angular/fire/compat/firestore'; import { trace } from '@angular/fire/compat/performance'; @@ -27,6 +27,7 @@ import { IonIcon, } from '@ionic/angular/standalone'; import { AsyncPipe, DatePipe, DecimalPipe } from '@angular/common'; +import { filterNullish } from 'src/app/shared/services/rxjs.service'; interface Attendance { user: Observable; @@ -59,13 +60,13 @@ interface Attendance { AsyncPipe, ], }) -export class ListPage implements OnInit { +export class ListPage { @ViewChild('mySwal') private mySwal!: SwalComponent; attendanceCollection$: Observable; eventID: string; - event$: Observable; + event$: Observable; constructor( private afs: AngularFirestore, @@ -92,12 +93,7 @@ export class ListPage implements OnInit { } }); - this.event$ = this.afs - .collection('events') - .doc(this.eventID) - .valueChanges() - // @ts-ignore - .pipe(trace('firestore')); + this.event$ = this.afs.collection('events').doc(this.eventID).valueChanges(); this.attendanceCollection$ = this.afs .collection(`events/${this.eventID}/attendance`, (ref) => { @@ -111,16 +107,13 @@ export class ListPage implements OnInit { return attendance.map((item) => { return { ...item, - // @ts-ignore - user: this.afs.collection('users').doc(item.id).valueChanges().pipe(trace('firestore'), take(1)), + user: this.afs.collection('users').doc(item.id).valueChanges().pipe(filterNullish(), take(1)), }; }); }) ); } - ngOnInit() {} - deleteAttendance(attendanceID: string) { this.afs .collection(`events/${this.eventID}/attendance`) @@ -223,6 +216,9 @@ export class ListPage implements OnInit { }); this.event$.pipe(take(1)).subscribe((event) => { + if (!event) { + return; + } const csvString = csv.map((row) => row.join(',')).join('\n'); const a = document.createElement('a'); a.href = window.URL.createObjectURL(new Blob([csvString], { type: 'text/csv' })); diff --git a/src/app/restricted-area/manage-events/list-attendances/list.routes.ts b/src/app/restricted-area/manage-events/list-attendances/list.routes.ts index d0290628..e921e6bf 100644 --- a/src/app/restricted-area/manage-events/list-attendances/list.routes.ts +++ b/src/app/restricted-area/manage-events/list-attendances/list.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { ListPage } from './list.page'; diff --git a/src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.html b/src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.html similarity index 100% rename from src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.html rename to src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.html diff --git a/src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.routes.ts b/src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.routes.ts new file mode 100644 index 00000000..8de66181 --- /dev/null +++ b/src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@angular/router'; +import { ListEventSubscriptionsPage } from './list-event-subscriptions'; + +export const routes: Routes = [ + { + path: '', + component: ListEventSubscriptionsPage, + }, +]; diff --git a/src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.scss b/src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.scss similarity index 100% rename from src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.scss rename to src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.scss diff --git a/src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.ts b/src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.ts similarity index 90% rename from src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.ts rename to src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.ts index c7ea3a59..f282f0c2 100644 --- a/src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.ts +++ b/src/app/restricted-area/manage-events/list-event-subscriptions/list-event-subscriptions.ts @@ -1,4 +1,5 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; +// @ts-strict-ignore +import { Component, ViewChild } from '@angular/core'; import { AngularFirestore } from '@angular/fire/compat/firestore'; import { trace } from '@angular/fire/compat/performance'; import { ActivatedRoute, Router } from '@angular/router'; @@ -33,9 +34,9 @@ interface Subscription { } @UntilDestroy() @Component({ - selector: 'app-list-subscriptions', - templateUrl: './list-subscriptions.html', - styleUrls: ['./list-subscriptions.scss'], + selector: 'app-list-event-subscriptions', + templateUrl: './list-event-subscriptions.html', + styleUrls: ['./list-event-subscriptions.scss'], standalone: true, imports: [ IonHeader, @@ -54,11 +55,11 @@ interface Subscription { DatePipe, ], }) -export class ListSubscriptionsPage implements OnInit { +export class ListEventSubscriptionsPage { @ViewChild('mySwal') private mySwal!: SwalComponent; - event$: Observable; + event$: Observable; subscriptions$: Observable; eventID: string; @@ -68,7 +69,7 @@ export class ListSubscriptionsPage implements OnInit { private router: Router, private route: ActivatedRoute, public courses: CoursesService, - public dateService: DateService + public dateService: DateService, ) { this.eventID = this.route.snapshot.params['eventID']; this.afs @@ -86,12 +87,7 @@ export class ListSubscriptionsPage implements OnInit { } }); - this.event$ = this.afs - .collection('events') - .doc(this.eventID) - .valueChanges() - // @ts-ignore - .pipe(trace('firestore')); + this.event$ = this.afs.collection('events').doc(this.eventID).valueChanges(); this.subscriptions$ = this.afs .collection(`events/${this.eventID}/subscriptions`, (ref) => ref.orderBy('time')) @@ -107,13 +103,11 @@ export class ListSubscriptionsPage implements OnInit { .doc(item.id) .get() .pipe(map((document) => document.data())), - })) - ) + })), + ), ); } - ngOnInit() {} - generateCSV() { this.afs .collection('users') diff --git a/src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.routes.ts b/src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.routes.ts deleted file mode 100644 index ddebd6b2..00000000 --- a/src/app/restricted-area/manage-events/list-subscriptions/list-subscriptions.routes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { RouterModule, Routes } from '@angular/router'; -import { ListSubscriptionsPage } from './list-subscriptions'; - -export const routes: Routes = [ - { - path: '', - component: ListSubscriptionsPage, - }, -]; diff --git a/src/app/restricted-area/manage-events/manage-events.page.html b/src/app/restricted-area/manage-events/manage-events.page.html index 08335cc9..44149816 100644 --- a/src/app/restricted-area/manage-events/manage-events.page.html +++ b/src/app/restricted-area/manage-events/manage-events.page.html @@ -48,6 +48,7 @@

Nenhum evento encontrado

@for (item of eventList; track item) { Emoji do evento

}
@if (subscription.image | async; as url) { - + Comprovante enviado pelo usuário } @else {

Imagem não encontrada

} @@ -146,7 +146,7 @@

Imagem não encontrada

Choque de horário - @if (refuseForm.get('radioGroup').value == 'invalidReceipt') { + @if (refuseForm.get('radioGroup').value === 'invalidReceipt') { diff --git a/src/app/restricted-area/manage-major-events/validate-receipt/validate-receipt.page.ts b/src/app/restricted-area/manage-major-events/validate-receipt/validate-receipt.page.ts index d569e0ff..7a547fa8 100644 --- a/src/app/restricted-area/manage-major-events/validate-receipt/validate-receipt.page.ts +++ b/src/app/restricted-area/manage-major-events/validate-receipt/validate-receipt.page.ts @@ -113,7 +113,7 @@ export class ValidateReceiptPage implements OnInit { @ViewChild('swalConfirm') private swalConfirm: SwalComponent; @ViewChild('refuseModal') private refuseModal: IonModal; - arrayIndex: number = 0; + arrayIndex = 0; constructor( private route: ActivatedRoute, @@ -121,7 +121,7 @@ export class ValidateReceiptPage implements OnInit { private formBuilder: FormBuilder, private alertController: AlertController, public dateService: DateService, - private toastController: ToastController, + private toastController: ToastController ) {} ngOnInit() { @@ -129,7 +129,7 @@ export class ValidateReceiptPage implements OnInit { const eventRef = this.afs.collection('majorEvents').doc(this.majorEventID); this.eventName$ = eventRef.valueChanges().pipe(map((event) => event.name)); this.subscriptionsQuery = eventRef.collection('subscriptions', (ref) => - ref.where('payment.status', '==', 1).orderBy('payment.time'), + ref.where('payment.status', '==', 1).orderBy('payment.time') ); this.subscriptions$ = this.subscriptionsQuery.valueChanges({ idField: 'id' }).pipe( untilDestroyed(this), @@ -141,7 +141,7 @@ export class ValidateReceiptPage implements OnInit { .collection('events') .doc(subEventID) .valueChanges({ idField: 'id' }) - .pipe(take(1), trace('firestore')), + .pipe(take(1), trace('firestore')) ); let observableArrayOfEvents: Observable = combineLatest(arrayOfEvents); @@ -151,7 +151,7 @@ export class ValidateReceiptPage implements OnInit { return events.sort((a, b) => { return a.eventStartDate.toMillis() - b.eventStartDate.toMillis(); }); - }), + }) ); return { @@ -160,8 +160,8 @@ export class ValidateReceiptPage implements OnInit { userData$: this.userDataByID(sub.id), image: this.imgURL(sub.id), }; - }), - ), + }) + ) ); this.imgBaseHref = [this.majorEventID, 'payment-receipts'].join('/'); this.refuseForm = this.formBuilder.group( @@ -171,7 +171,7 @@ export class ValidateReceiptPage implements OnInit { }, { validators: [this.validatorRadio], - }, + } ); } @@ -198,7 +198,7 @@ export class ValidateReceiptPage implements OnInit { .subscribe((col) => { const subscriberID = col.docs[this.arrayIndex].id; this.subscriptionsQuery.doc(subscriberID).update({ - // @ts-ignore + // @ts-expect-error - This works 'payment.status': 2, // Novo status: pagamento aprovado 'payment.time': serverTimestamp(), 'payment.author': adminUser.uid, // Autor da mudança @@ -217,7 +217,6 @@ export class ValidateReceiptPage implements OnInit { .collection('subscriptions') .doc(subscriberID) .set({ - // @ts-ignore time: serverTimestamp(), }); @@ -266,7 +265,7 @@ export class ValidateReceiptPage implements OnInit { switch (this.refuseForm.value.radioGroup) { case 'invalidReceipt': this.subscriptionsQuery.doc(subscriberID).update({ - // @ts-ignore + // @ts-expect-error - This works 'payment.status': 3, 'payment.validationTime': serverTimestamp(), 'payment.validationAuthor': user.uid, @@ -292,14 +291,14 @@ export class ValidateReceiptPage implements OnInit { firstName, user.phone, eventName, - this.refuseForm.get('errorMessage').value, + this.refuseForm.get('errorMessage').value ); }); }); break; case 'noSlots': this.subscriptionsQuery.doc(subscriberID).update({ - // @ts-ignore + // @ts-expect-error - This works 'payment.status': 4, 'payment.validationTime': serverTimestamp(), 'payment.validationAuthor': user.uid, @@ -330,7 +329,7 @@ export class ValidateReceiptPage implements OnInit { case 'scheduleConflict': this.subscriptionsQuery.doc(subscriberID).update({ - // @ts-ignore + // @ts-expect-error - This works 'payment.status': 5, 'payment.validationTime': serverTimestamp(), 'payment.validationAuthor': user.uid, @@ -380,7 +379,7 @@ export class ValidateReceiptPage implements OnInit { handler: () => { const formattedPhone = this.formatPhoneWhatsApp(phone); - const text: string = `Olá, ${name}! O seu comprovante de pagamento do evento "${event}" foi recusado.%0aA justificativa é "${message}".%0a%0aRealize o envio novamente pelo link:%0a${environment.baseUrl}inscricoes/pagar/${this.majorEventID}?utm_source=whatsapp%26utm_medium=message%26utm_campaign=payment_error`; + const text = `Olá, ${name}! O seu comprovante de pagamento do evento "${event}" foi recusado.%0aA justificativa é "${message}".%0a%0aRealize o envio novamente pelo link:%0a${environment.baseUrl}inscricoes/pagar/${this.majorEventID}?utm_source=whatsapp%26utm_medium=message%26utm_campaign=payment_error`; const url = `https://api.whatsapp.com/send?phone=${formattedPhone}&text=${text}`; window.open(url, '_blank'); @@ -407,7 +406,7 @@ export class ValidateReceiptPage implements OnInit { handler: () => { const formattedPhone = this.formatPhoneWhatsApp(phone); - const text: string = `Olá, ${name}! Ocorreu um problema com a sua inscrição no evento "${event}".%0aNão há mais vagas em uma das atividades selecionadas.%0a%0aVocê precisa editar a sua inscrição pelo link:%0a${environment.baseUrl}eventos/inscrever/${this.majorEventID}?utm_source=whatsapp%26utm_medium=message%26utm_campaign=no_slots`; + const text = `Olá, ${name}! Ocorreu um problema com a sua inscrição no evento "${event}".%0aNão há mais vagas em uma das atividades selecionadas.%0a%0aVocê precisa editar a sua inscrição pelo link:%0a${environment.baseUrl}eventos/inscrever/${this.majorEventID}?utm_source=whatsapp%26utm_medium=message%26utm_campaign=no_slots`; const url = `https://api.whatsapp.com/send?phone=${formattedPhone}&text=${text}`; window.open(url, '_blank'); }, @@ -433,7 +432,7 @@ export class ValidateReceiptPage implements OnInit { handler: () => { const formattedPhone = this.formatPhoneWhatsApp(phone); - const text: string = `Olá, ${name}! Ocorreu um problema com a sua inscrição no evento "${event}".%0aHá um choque de horário nos eventos que você selecionou.%0a%0aVocê precisa editar a sua inscrição pelo link:%0a${environment.baseUrl}eventos/inscrever/${this.majorEventID}?utm_source=whatsapp%26utm_medium=message%26utm_campaign=schedule_conflict`; + const text = `Olá, ${name}! Ocorreu um problema com a sua inscrição no evento "${event}".%0aHá um choque de horário nos eventos que você selecionou.%0a%0aVocê precisa editar a sua inscrição pelo link:%0a${environment.baseUrl}eventos/inscrever/${this.majorEventID}?utm_source=whatsapp%26utm_medium=message%26utm_campaign=schedule_conflict`; const url = `https://api.whatsapp.com/send?phone=${formattedPhone}&text=${text}`; window.open(url, '_blank'); }, @@ -478,7 +477,7 @@ export class ValidateReceiptPage implements OnInit { let string = array.join('\n'); // Remove all quotes and brackets - string = string.replace(/[\[\]"]+/g, ''); + string = string.replace(/[[\]"]+/g, ''); const toast = await this.toastController.create({ header: 'IDs dos eventos', diff --git a/src/app/restricted-area/manage-major-events/validate-receipt/validate-receipt.routes.ts b/src/app/restricted-area/manage-major-events/validate-receipt/validate-receipt.routes.ts index 4a14fdcd..62a0aa84 100644 --- a/src/app/restricted-area/manage-major-events/validate-receipt/validate-receipt.routes.ts +++ b/src/app/restricted-area/manage-major-events/validate-receipt/validate-receipt.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { ValidateReceiptPage } from './validate-receipt.page'; diff --git a/src/app/restricted-area/restricted-area.page.ts b/src/app/restricted-area/restricted-area.page.ts index 62cc87c8..21c6576e 100644 --- a/src/app/restricted-area/restricted-area.page.ts +++ b/src/app/restricted-area/restricted-area.page.ts @@ -1,20 +1,39 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { RouterLink } from '@angular/router'; -import { addIcons } from "ionicons"; -import { listOutline, peopleOutline } from "ionicons/icons"; -import { IonRouterLink, IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonItem, IonIcon, IonLabel } from "@ionic/angular/standalone"; +import { addIcons } from 'ionicons'; +import { listOutline, peopleOutline } from 'ionicons/icons'; +import { + IonRouterLink, + IonHeader, + IonToolbar, + IonTitle, + IonContent, + IonCard, + IonItem, + IonIcon, + IonLabel, +} from '@ionic/angular/standalone'; @Component({ - selector: 'app-restricted-area', - templateUrl: './restricted-area.page.html', - styleUrls: ['./restricted-area.page.scss'], - standalone: true, - imports: [RouterLink, IonRouterLink, IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonItem, IonIcon, IonLabel], + selector: 'app-restricted-area', + templateUrl: './restricted-area.page.html', + styleUrls: ['./restricted-area.page.scss'], + standalone: true, + imports: [ + RouterLink, + IonRouterLink, + IonHeader, + IonToolbar, + IonTitle, + IonContent, + IonCard, + IonItem, + IonIcon, + IonLabel, + ], }) -export class RestrictedAreaPage implements OnInit { - constructor() { - addIcons({ listOutline, peopleOutline }); - } - - ngOnInit() { } +export class RestrictedAreaPage { + constructor() { + addIcons({ listOutline, peopleOutline }); + } } diff --git a/src/app/restricted-area/restricted-area.routes.ts b/src/app/restricted-area/restricted-area.routes.ts index 8050a889..14c2605a 100644 --- a/src/app/restricted-area/restricted-area.routes.ts +++ b/src/app/restricted-area/restricted-area.routes.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { RestrictedAreaPage } from './restricted-area.page'; diff --git a/src/app/shared/components/aztec-scanner/aztec-scanner.component.ts b/src/app/shared/components/aztec-scanner/aztec-scanner.component.ts index 2fb281a6..e2bcabe6 100644 --- a/src/app/shared/components/aztec-scanner/aztec-scanner.component.ts +++ b/src/app/shared/components/aztec-scanner/aztec-scanner.component.ts @@ -12,22 +12,22 @@ import { ReadResult, readBarcodesFromImageData } from 'zxing-wasm'; styleUrls: ['./aztec-scanner.component.scss'], standalone: true, }) -export class ScannerVideoComponent implements AfterViewInit { - isAutostarting: boolean = false; +export class AztecScannerComponent implements AfterViewInit { + isAutostarting = false; scannerCanvas: HTMLCanvasElement; ctx: CanvasRenderingContext2D; - @Output() deviceList: EventEmitter = new EventEmitter(); - @Output() noCamerasFound: EventEmitter = new EventEmitter(); - @Output() hasPermission: EventEmitter = new EventEmitter(false); - @Output() scanSuccess: EventEmitter = new EventEmitter(); + @Output() deviceList = new EventEmitter(); + @Output() noCamerasFound = new EventEmitter(); + @Output() hasPermission = new EventEmitter(false); + @Output() scanSuccess = new EventEmitter(); - @Input() delaySeconds: number = 1; + @Input() delaySeconds = 1; @ViewChild('scannerVideo') videoElemRef!: ElementRef; - _hasPermission: boolean = false; + _hasPermission = false; /** * The device that should be used to scan things. @@ -162,6 +162,7 @@ export class ScannerVideoComponent implements AfterViewInit { continue; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any const deviceId = device.deviceId || (device as any).id; const label = device.label || `Video device ${videoDevices.length + 1}`; const groupId = device.groupId; @@ -184,7 +185,7 @@ export class ScannerVideoComponent implements AfterViewInit { } let stream: MediaStream | undefined; - let permission: boolean = false; + let permission = false; try { // Will try to ask for permission @@ -192,6 +193,7 @@ export class ScannerVideoComponent implements AfterViewInit { permission = !!stream; } catch (error) { + console.error('Error getting permission:', error); if (stream) { this.terminateStream(stream); } @@ -201,6 +203,7 @@ export class ScannerVideoComponent implements AfterViewInit { if (stream) { this.terminateStream(stream); } + // eslint-disable-next-line no-unsafe-finally return permission; } } @@ -265,7 +268,7 @@ export class ScannerVideoComponent implements AfterViewInit { const ctx = this.ctx; ctx.drawImage(video, 0, 0, canvas.width, canvas.height); - let imageData = canvas.getContext('2d')?.getImageData(0, 0, canvas.width, canvas.height); + const imageData = canvas.getContext('2d')?.getImageData(0, 0, canvas.width, canvas.height); if (!imageData) { console.error('No image data found.'); @@ -290,7 +293,7 @@ export class ScannerVideoComponent implements AfterViewInit { const timeout = !result ? 0 : delay; setTimeout( () => requestAnimationFrame(this.processFrame.bind(this, delay)), // Bind the processFrame method to the current instance of the class. - timeout, + timeout ); } diff --git a/src/app/shared/components/aztec-scanner/services/navigator-utils.service.ts b/src/app/shared/components/aztec-scanner/services/navigator-utils.service.ts index 76a5b801..b2de801b 100644 --- a/src/app/shared/components/aztec-scanner/services/navigator-utils.service.ts +++ b/src/app/shared/components/aztec-scanner/services/navigator-utils.service.ts @@ -3,9 +3,7 @@ import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) -export class NavigatorUtilsService { - constructor() {} -} +export class NavigatorUtilsService {} /** * If navigator is present. @@ -23,7 +21,5 @@ function isMediaDevicesSupported() { * If enumerateDevices under navigator is supported. */ export function canEnumerateDevices() { - return !!( - isMediaDevicesSupported() && navigator.mediaDevices.enumerateDevices - ); + return !!(isMediaDevicesSupported() && navigator.mediaDevices.enumerateDevices); } diff --git a/src/app/shared/components/event-display/buttons/buttons.component.html b/src/app/shared/components/event-display/buttons/buttons.component.html index 0d046dc3..eaac55db 100644 --- a/src/app/shared/components/event-display/buttons/buttons.component.html +++ b/src/app/shared/components/event-display/buttons/buttons.component.html @@ -1,97 +1,64 @@ @if (eventItem.button) { -
- {{ - eventItem.button.text || 'Acompanhe o evento' - }} -
-} - -@if (eventItem.youtubeCode) { -
-

Transmissão do evento

- -
+
}
-@if (displaySubscriptionAttendanceButtons === true) { + @if (displaySubscriptionAttendanceButtons === true) {
- @if (eventItem.eventEndDate) { - @if (dateService.today() < dateService.getDateFromTimestamp(eventItem.eventEndDate)) { - @if (eventItem.allowSubscription && (isUserAuthenticated | async)) { - @if (!subscribedToEvent && !disableSubscriptionNoSlotsLeft) { - - Inscrever-se - - } - @else if (!subscribedToEvent && disableSubscriptionNoSlotsLeft) { - - Não há mais vagas - - } - @else if (subscribedToEvent) { - - Inscrito - - } - } - @if (eventItem.allowSubscription && !(isUserAuthenticated | async)) { - @if (!disableSubscriptionNoSlotsLeft) { - - Inscrever-se - - } - @if (disableSubscriptionNoSlotsLeft) { - - Não há mais vagas - - } - } - } - } + @if (eventItem.eventEndDate) { @if (dateService.today() < dateService.getDateFromTimestamp(eventItem.eventEndDate)) + { @if (eventItem.allowSubscription && (isUserAuthenticated | async)) { @if (!subscribedToEvent && + !disableSubscriptionNoSlotsLeft) { + Inscrever-se + } @else if (!subscribedToEvent && disableSubscriptionNoSlotsLeft) { + Não há mais vagas + } @else if (subscribedToEvent) { + + Inscrito + + } } @if (eventItem.allowSubscription && (isUserAuthenticated | async) === undefined) { @if + (!disableSubscriptionNoSlotsLeft) { + + Inscrever-se + + } @if (disableSubscriptionNoSlotsLeft) { + Não há mais vagas + } } } }
- @if (eventItem.collectAttendance) { - @if (eventItem.attendanceCollectionStart && !eventItem.attendanceCollectionEnd) { - @if (eventItem.allowSubscription && (isUserAuthenticated | async)) { - - Confirmar presença - - } - @if (eventItem.allowSubscription && !(isUserAuthenticated | async)) { - - Confirmar presença - - } - } - } -} + @if (eventItem.collectAttendance) { @if (eventItem.attendanceCollectionStart && !eventItem.attendanceCollectionEnd) { + @if (eventItem.allowSubscription && (isUserAuthenticated | async)) { + + Confirmar presença + + } @if (eventItem.allowSubscription && (isUserAuthenticated | async) === undefined) { + + Confirmar presença + + } } } }
diff --git a/src/app/shared/components/event-display/buttons/buttons.component.ts b/src/app/shared/components/event-display/buttons/buttons.component.ts index e459efe4..3422623c 100644 --- a/src/app/shared/components/event-display/buttons/buttons.component.ts +++ b/src/app/shared/components/event-display/buttons/buttons.component.ts @@ -37,7 +37,7 @@ export class ButtonsComponent implements OnInit { userID: string | undefined; subscribedToEvent: boolean | undefined; isUserAuthenticated: Observable; - disableSubscriptionNoSlotsLeft: boolean = false; + disableSubscriptionNoSlotsLeft = false; constructor( private toastController: ToastController, @@ -102,7 +102,6 @@ export class ButtonsComponent implements OnInit { this.afs .doc(`events/${eventID}/subscriptions/${user.uid}`) .set({ - // @ts-ignore time: serverTimestamp(), }) .then(() => { @@ -121,7 +120,6 @@ export class ButtonsComponent implements OnInit { this.afs .doc(`events/${this.eventItem.id}/subscriptions/${user.uid}`) .set({ - // @ts-ignore time: serverTimestamp(), }) .then(() => { diff --git a/src/app/shared/components/event-display/description/description.component.ts b/src/app/shared/components/event-display/description/description.component.ts deleted file mode 100644 index 2a162613..00000000 --- a/src/app/shared/components/event-display/description/description.component.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { EventItem } from '../../../services/event'; -import { Component, Input, OnInit } from '@angular/core'; - -/** - * Requires the eventItem input to be passed in. - */ -@Component({ - selector: 'app-event-display-description[eventItem]', - templateUrl: './description.component.html', - styleUrls: ['./description.component.scss'], - standalone: true, -}) -export class DescriptionComponent implements OnInit { - @Input() eventItem!: EventItem; - - constructor() {} - - ngOnInit() {} -} diff --git a/src/app/shared/components/event-display/description/description.component.html b/src/app/shared/components/event-display/event-description/event-description.component.html similarity index 100% rename from src/app/shared/components/event-display/description/description.component.html rename to src/app/shared/components/event-display/event-description/event-description.component.html diff --git a/src/app/shared/components/event-display/description/description.component.scss b/src/app/shared/components/event-display/event-description/event-description.component.scss similarity index 100% rename from src/app/shared/components/event-display/description/description.component.scss rename to src/app/shared/components/event-display/event-description/event-description.component.scss diff --git a/src/app/shared/components/event-display/event-description/event-description.component.ts b/src/app/shared/components/event-display/event-description/event-description.component.ts new file mode 100644 index 00000000..23ecc7f5 --- /dev/null +++ b/src/app/shared/components/event-display/event-description/event-description.component.ts @@ -0,0 +1,15 @@ +import { EventItem } from '../../../services/event'; +import { Component, Input } from '@angular/core'; + +/** + * Requires the eventItem input to be passed in. + */ +@Component({ + selector: 'app-event-description[eventItem]', + templateUrl: './event-description.component.html', + styleUrls: ['./event-description.component.scss'], + standalone: true, +}) +export class EventDescriptionComponent { + @Input() eventItem!: EventItem; +} diff --git a/src/app/shared/components/event-display/event-header/event-header.component.html b/src/app/shared/components/event-display/event-header/event-header.component.html new file mode 100644 index 00000000..85680563 --- /dev/null +++ b/src/app/shared/components/event-display/event-header/event-header.component.html @@ -0,0 +1,39 @@ +Emoji do evento + +
+

{{ eventItem.name }}

+
{{ eventItem.shortDescription }}
+
{{ coursesService.getCourse(eventItem.course) }}
+

+ + {{ stringService.toUppercase(dateService.getDateFromTimestamp(eventItem.eventStartDate) | date: "EEEE, dd 'de' MMMM 'de' y") }} +

+

+ {{ dateService.getDateFromTimestamp(eventItem.eventStartDate) | date : 'HH:mm' }} + @if (eventItem.eventEndDate) { - {{ dateService.getDateFromTimestamp(eventItem.eventEndDate) | date : 'HH:mm' }} + } +

+ + @if (displayWeather === true) { +
+ @if (weather | async; as weatherInfo) { @if (!weatherInfo.error) { + + {{ weatherInfo.temperature }}°C – {{ weatherInfo.text }} + } } +
+ } +
+ +@if (weather | async) { + +} diff --git a/src/app/shared/components/event-display/header/header.component.scss b/src/app/shared/components/event-display/event-header/event-header.component.scss similarity index 100% rename from src/app/shared/components/event-display/header/header.component.scss rename to src/app/shared/components/event-display/event-header/event-header.component.scss diff --git a/src/app/shared/components/event-display/header/header.component.ts b/src/app/shared/components/event-display/event-header/event-header.component.ts similarity index 79% rename from src/app/shared/components/event-display/header/header.component.ts rename to src/app/shared/components/event-display/event-header/event-header.component.ts index be9354c6..9bbb3d1b 100644 --- a/src/app/shared/components/event-display/header/header.component.ts +++ b/src/app/shared/components/event-display/event-header/event-header.component.ts @@ -4,9 +4,9 @@ import { Observable } from 'rxjs'; import { WeatherInfo, WeatherService } from '../../../services/weather.service'; import { DateService } from '../../../services/date.service'; -import { CoursesService } from './../../../services/courses.service'; -import { StringManagementService } from './../../../services/string-management.service'; -import { EmojiService } from './../../../services/emoji.service'; +import { CoursesService } from '../../../services/courses.service'; +import { StringManagementService } from '../../../services/string-management.service'; +import { EmojiService } from '../../../services/emoji.service'; import { EventItem } from '../../../services/event'; import { IonCardHeader, IonCardTitle, IonIcon, IonText } from '@ionic/angular/standalone'; import { DatePipe, AsyncPipe } from '@angular/common'; @@ -15,18 +15,18 @@ import { DatePipe, AsyncPipe } from '@angular/common'; * Requires the eventItem input to be passed in. */ @Component({ - selector: 'app-event-display-header[eventItem]', - templateUrl: './header.component.html', - styleUrls: ['./header.component.scss'], + selector: 'app-event-header[eventItem]', + templateUrl: './event-header.component.html', + styleUrls: ['./event-header.component.scss'], standalone: true, imports: [IonCardHeader, IonCardTitle, IonIcon, IonText, DatePipe, AsyncPipe], }) -export class HeaderComponent implements OnInit { +export class EventHeaderComponent implements OnInit { @Input() eventItem!: EventItem; @Input() displayWeather: boolean | undefined; weather: Observable | undefined; - weatherFailed: boolean = false; + weatherFailed = false; constructor( public coursesService: CoursesService, @@ -34,7 +34,7 @@ export class HeaderComponent implements OnInit { private weatherService: WeatherService, public dateService: DateService, public stringService: StringManagementService, - public emojiService: EmojiService + public emojiService: EmojiService, ) {} ngOnInit() { @@ -46,7 +46,7 @@ export class HeaderComponent implements OnInit { this.weather = this.weatherService.getWeather( this.dateService.getDateFromTimestamp(this.eventItem.eventStartDate), this.eventItem.location.lat, - this.eventItem.location.lon + this.eventItem.location.lon, ); } } diff --git a/src/app/shared/components/event-display/header/header.component.html b/src/app/shared/components/event-display/header/header.component.html deleted file mode 100644 index e7224236..00000000 --- a/src/app/shared/components/event-display/header/header.component.html +++ /dev/null @@ -1,36 +0,0 @@ - - -
-

{{ eventItem.name }}

-
{{ eventItem.shortDescription }}
-
{{ coursesService.getCourse(eventItem.course) }}
-

- - {{ stringService.toUppercase(dateService.getDateFromTimestamp(eventItem.eventStartDate) | date: "EEEE, dd 'de' MMMM 'de' y") }} -

-

- {{ dateService.getDateFromTimestamp(eventItem.eventStartDate) | date: 'HH:mm' }} - @if (eventItem.eventEndDate) { - - {{ dateService.getDateFromTimestamp(eventItem.eventEndDate) | date: 'HH:mm' }} - } -

- - @if (displayWeather === true) { -
- @if (weather | async; as weatherInfo) { - @if (!weatherInfo.error) { - - {{ weatherInfo.temperature }}°C – {{ weatherInfo.text }} - } - } -
- } -
- -@if (weather | async) { - -} diff --git a/src/app/shared/components/event-display/map/map.component.ts b/src/app/shared/components/event-display/map/map.component.ts index c719a133..d6e9de43 100644 --- a/src/app/shared/components/event-display/map/map.component.ts +++ b/src/app/shared/components/event-display/map/map.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, OnDestroy, OnChanges } from '@angular/core'; import Map from 'ol/Map'; import View from 'ol/View'; @@ -6,7 +6,7 @@ import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'; import OSM from 'ol/source/OSM'; import Feature from 'ol/Feature'; import { Icon, Style } from 'ol/style'; -import { fromLonLat, useGeographic } from 'ol/proj'; +import { useGeographic } from 'ol/proj'; import Point from 'ol/geom/Point'; import VectorSource from 'ol/source/Vector'; @@ -24,12 +24,10 @@ import { IonItem, IonIcon, IonLabel } from '@ionic/angular/standalone'; standalone: true, imports: [IonItem, IonIcon, IonLabel], }) -export class MapComponent implements OnInit { +export class MapComponent implements OnInit, OnDestroy, OnChanges { map: Map | undefined | null; @Input() eventItem!: EventItem; - constructor() {} - ngOnInit() { this.generateMap(); } @@ -62,7 +60,7 @@ export class MapComponent implements OnInit { }), }); - let iconFeature = new Feature({ + const iconFeature = new Feature({ geometry: new Point([this.eventItem.location.lon, this.eventItem.location.lat]), name: this.eventItem.name, }); diff --git a/src/app/shared/components/major-event-display/date/date.component.ts b/src/app/shared/components/major-event-display/date/date.component.ts index 2f5b8b2e..d0a68c80 100644 --- a/src/app/shared/components/major-event-display/date/date.component.ts +++ b/src/app/shared/components/major-event-display/date/date.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { DateService } from 'src/app/shared/services/date.service'; import { MajorEventItem } from 'src/app/shared/services/major-event.service'; @@ -15,10 +15,8 @@ import { DatePipe } from '@angular/common'; standalone: true, imports: [IonIcon, IonItem, DatePipe], }) -export class DateComponent implements OnInit { +export class DateComponent { @Input() majorEventItem!: MajorEventItem; constructor(public dateService: DateService) {} - - ngOnInit() {} } diff --git a/src/app/shared/components/major-event-display/description/description.component.html b/src/app/shared/components/major-event-display/major-event-description/major-event-description.component.html similarity index 100% rename from src/app/shared/components/major-event-display/description/description.component.html rename to src/app/shared/components/major-event-display/major-event-description/major-event-description.component.html diff --git a/src/app/shared/components/major-event-display/description/description.component.scss b/src/app/shared/components/major-event-display/major-event-description/major-event-description.component.scss similarity index 100% rename from src/app/shared/components/major-event-display/description/description.component.scss rename to src/app/shared/components/major-event-display/major-event-description/major-event-description.component.scss diff --git a/src/app/shared/components/major-event-display/description/description.component.ts b/src/app/shared/components/major-event-display/major-event-description/major-event-description.component.ts similarity index 50% rename from src/app/shared/components/major-event-display/description/description.component.ts rename to src/app/shared/components/major-event-display/major-event-description/major-event-description.component.ts index def5c8bd..f890dfc6 100644 --- a/src/app/shared/components/major-event-display/description/description.component.ts +++ b/src/app/shared/components/major-event-display/major-event-description/major-event-description.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { MajorEventItem } from 'src/app/shared/services/major-event.service'; import { IonCardContent } from '@ionic/angular/standalone'; @@ -6,16 +6,12 @@ import { IonCardContent } from '@ionic/angular/standalone'; * Requires the majorEventItem input to be passed in. */ @Component({ - selector: 'app-major-event-display-description[majorEventItem]', - templateUrl: './description.component.html', - styleUrls: ['./description.component.scss'], + selector: 'app-major-event-description[majorEventItem]', + templateUrl: './major-event-description.component.html', + styleUrls: ['./major-event-description.component.scss'], standalone: true, imports: [IonCardContent], }) -export class DescriptionComponent implements OnInit { +export class MajorEventDescriptionComponent { @Input() majorEventItem!: MajorEventItem; - - constructor() {} - - ngOnInit() {} } diff --git a/src/app/shared/components/major-event-display/header/header.component.html b/src/app/shared/components/major-event-display/major-event-header/major-event-header.component.html similarity index 100% rename from src/app/shared/components/major-event-display/header/header.component.html rename to src/app/shared/components/major-event-display/major-event-header/major-event-header.component.html diff --git a/src/app/shared/components/major-event-display/header/header.component.scss b/src/app/shared/components/major-event-display/major-event-header/major-event-header.component.scss similarity index 100% rename from src/app/shared/components/major-event-display/header/header.component.scss rename to src/app/shared/components/major-event-display/major-event-header/major-event-header.component.scss diff --git a/src/app/shared/components/major-event-display/header/header.component.ts b/src/app/shared/components/major-event-display/major-event-header/major-event-header.component.ts similarity index 53% rename from src/app/shared/components/major-event-display/header/header.component.ts rename to src/app/shared/components/major-event-display/major-event-header/major-event-header.component.ts index 4e417631..62514e0b 100644 --- a/src/app/shared/components/major-event-display/header/header.component.ts +++ b/src/app/shared/components/major-event-display/major-event-header/major-event-header.component.ts @@ -1,20 +1,16 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { MajorEventItem } from 'src/app/shared/services/major-event.service'; import { IonCardHeader, IonCardTitle } from '@ionic/angular/standalone'; @Component({ // Requires the majorEventItem input to be passed in. - selector: 'app-major-event-display-header[majorEventItem]', - templateUrl: './header.component.html', - styleUrls: ['./header.component.scss'], + selector: 'app-major-event-header[majorEventItem]', + templateUrl: './major-event-header.component.html', + styleUrls: ['./major-event-header.component.scss'], standalone: true, imports: [IonCardHeader, IonCardTitle], }) -export class HeaderComponent implements OnInit { +export class MajorEventHeaderComponent { @Input() majorEventItem!: MajorEventItem; - - constructor() {} - - ngOnInit() {} } diff --git a/src/app/shared/components/major-event-display/price/price.component.ts b/src/app/shared/components/major-event-display/price/price.component.ts index 0ee29d9f..45ea7fe7 100644 --- a/src/app/shared/components/major-event-display/price/price.component.ts +++ b/src/app/shared/components/major-event-display/price/price.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { MajorEventItem } from 'src/app/shared/services/major-event.service'; import { IonIcon, IonItem, IonLabel } from '@ionic/angular/standalone'; import { CurrencyPipe } from '@angular/common'; @@ -13,10 +13,6 @@ import { CurrencyPipe } from '@angular/common'; standalone: true, imports: [IonIcon, IonItem, IonLabel, CurrencyPipe], }) -export class PriceComponent implements OnInit { +export class PriceComponent { @Input() majorEventItem!: MajorEventItem; - - constructor() {} - - ngOnInit() {} } diff --git a/src/app/shared/directives/click-stop-propagation.ts b/src/app/shared/directives/click-stop-propagation.ts index 07955924..580e9df9 100644 --- a/src/app/shared/directives/click-stop-propagation.ts +++ b/src/app/shared/directives/click-stop-propagation.ts @@ -4,11 +4,12 @@ import { Directive, HostListener } from '@angular/core'; @Directive({ - selector: '[click-stop-propagation]', + selector: '[appClickStopPropagation]', standalone: true, }) -export class ClickStopPropagation { +export class ClickStopPropagationDirective { @HostListener('click', ['$event']) + // eslint-disable-next-line @typescript-eslint/no-explicit-any public onClick(event: any): void { event.stopPropagation(); } diff --git a/src/app/shared/pipes/safe.pipe.ts b/src/app/shared/pipes/safe.pipe.ts index 502f3051..839d83d0 100644 --- a/src/app/shared/pipes/safe.pipe.ts +++ b/src/app/shared/pipes/safe.pipe.ts @@ -2,21 +2,27 @@ import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer, SafeHtml, SafeStyle, SafeScript, SafeUrl, SafeResourceUrl } from '@angular/platform-browser'; @Pipe({ - name: 'safe', - standalone: true + name: 'safe', + standalone: true, }) export class SafePipe implements PipeTransform { - constructor(protected sanitizer: DomSanitizer) {} - - public transform(value: any, type: string): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl { + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public transform(value: any, type: string): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl { switch (type) { - case 'html': return this.sanitizer.bypassSecurityTrustHtml(value); - case 'style': return this.sanitizer.bypassSecurityTrustStyle(value); - case 'script': return this.sanitizer.bypassSecurityTrustScript(value); - case 'url': return this.sanitizer.bypassSecurityTrustUrl(value); - case 'resourceUrl': return this.sanitizer.bypassSecurityTrustResourceUrl(value); - default: throw new Error(`Invalid safe type specified: ${type}`); - } + case 'html': + return this.sanitizer.bypassSecurityTrustHtml(value); + case 'style': + return this.sanitizer.bypassSecurityTrustStyle(value); + case 'script': + return this.sanitizer.bypassSecurityTrustScript(value); + case 'url': + return this.sanitizer.bypassSecurityTrustUrl(value); + case 'resourceUrl': + return this.sanitizer.bypassSecurityTrustResourceUrl(value); + default: + throw new Error(`Invalid safe type specified: ${type}`); + } } } diff --git a/src/app/shared/services/auth.service.ts b/src/app/shared/services/auth.service.ts index dc6ecd81..90db2abb 100644 --- a/src/app/shared/services/auth.service.ts +++ b/src/app/shared/services/auth.service.ts @@ -53,7 +53,7 @@ export class AuthService { public ngZone: NgZone, public modalController: ModalController, public toastController: ToastController, - private route: ActivatedRoute, + private route: ActivatedRoute ) { this.authState$.pipe(trace('auth')).subscribe((user) => { if (user) { @@ -121,7 +121,7 @@ export class AuthService { .collection('users') .doc(this.userData.uid) .update({ - // @ts-ignore + // @ts-expect-error - This works pending: { onlineAttendance: arrayRemove(eventID) }, }); } @@ -240,6 +240,7 @@ export class AuthService { toast.present(); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any async toastAccountLinkFailed(error: any) { let header: string; let message: string; @@ -305,12 +306,12 @@ export class AuthService { } } return true; - }), + }) ); } return null; }), - switchMap((value) => value), + switchMap((value) => value) ); } diff --git a/src/app/shared/services/certificates.service.ts b/src/app/shared/services/certificates.service.ts index 0418468f..c3895608 100644 --- a/src/app/shared/services/certificates.service.ts +++ b/src/app/shared/services/certificates.service.ts @@ -21,15 +21,12 @@ import { environment } from 'src/environments/environment'; providedIn: 'root', }) export class CertificateService { - constructor( - private afs: AngularFirestore, - private http: HttpClient, - ) {} + constructor(private afs: AngularFirestore, private http: HttpClient) {} generateCertificate( eventID: string, certificateStoreData: CertificateStoreData, - certificateUserData: UserCertificateDocument, + certificateUserData: UserCertificateDocument ) { if (!certificateUserData || !certificateStoreData) { throw new Error('Request is malformed'); @@ -37,7 +34,7 @@ export class CertificateService { throw new Error('Request is malformed: id is missing'); } - let pdfJson: Observable; + let pdfJson: Observable; const pdfPath = `assets/certificates/templates/${certificateStoreData.certificateTemplate}.json`; if (isDevMode()) { pdfJson = this.http.get(pdfPath, { @@ -51,7 +48,7 @@ export class CertificateService { const certificateData$ = this.afs .doc( - `/certificates/${eventID}/${certificateStoreData.id}/${certificateUserData.certificateDoc}`, + `/certificates/${eventID}/${certificateStoreData.id}/${certificateUserData.certificateDoc}` ) .get(); @@ -63,7 +60,7 @@ export class CertificateService { const content$ = this.getCertificateContent( eventID, certificateStoreData.id!, - certificateUserData.certificateDoc!, + certificateUserData.certificateDoc! ); const InterRegular$ = this.http .get('https://cdn.jsdelivr.net/gh/cacic-fct/fonts@main/Inter/latin-ext/inter-v12-latin-ext-regular.woff', { @@ -90,7 +87,7 @@ export class CertificateService { InterMedium$, InterLight$, ]); - }), + }) ) .pipe(take(1)) .subscribe(async ([certificateData, pdf, majorEvent, content, InterRegular, InterMedium, InterLight]) => { @@ -124,7 +121,7 @@ export class CertificateService { const encodedString: string = this.encodeCertificateCode( eventID, certificateStoreData.id!, - certificateUserData.certificateDoc, + certificateUserData.certificateDoc ); const verificationURLQR = `${environment.baseUrl}certificado/verificar/${encodedString}`; @@ -136,7 +133,7 @@ export class CertificateService { throw new Error('Major event is missing'); } - let input = { + const input = { name: certificateDataSnapshot.fullName, name_small: certificateDataSnapshot.fullName, event_name: majorEventData.name, @@ -159,7 +156,7 @@ export class CertificateService { const inputs = [input]; PDFGenerate({ - // TODO: Remove me when upstream fixes i + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore template, inputs, @@ -209,7 +206,7 @@ export class CertificateService { } else { throw new Error('Unable to generate content, certificate does not exist'); } - }), + }) ); } @@ -220,7 +217,7 @@ export class CertificateService { } function generateContent( eventInfoCache: Observable[], - eventsUserAttended: string[], + eventsUserAttended: string[] ): Observable { const eventInfo$ = combineLatest(eventInfoCache); @@ -261,7 +258,10 @@ function generateContent( // Get the events the user attended from the group const groupEventsAttended = groupEvents.filter((e) => { - return eventsUserAttended.includes(e?.id!); + if (e?.id === undefined) { + throw new Error('Event ID is missing'); + } + return eventsUserAttended.includes(e?.id); }); // Append all events of group to skip array @@ -277,9 +277,9 @@ function generateContent( continue; } - let creditHours: number = 0; + let creditHours = 0; // let creditHoursTotal: number = 0; - let eventDays: Timestamp[] = []; + const eventDays: Timestamp[] = []; // Sum credit hours of all events in group for (const e of groupEventsAttended) { @@ -350,7 +350,7 @@ function generateContent( content += `\nObservações:\nDatas em formato "dia/mês/ano".`; return content; - }), + }) ); } diff --git a/src/app/shared/services/courses.service.ts b/src/app/shared/services/courses.service.ts index c28c617c..6c07142f 100644 --- a/src/app/shared/services/courses.service.ts +++ b/src/app/shared/services/courses.service.ts @@ -68,9 +68,7 @@ export class CoursesService { } } -interface courseList { - [key: string]: { +type courseList = Record; diff --git a/src/app/shared/services/date.service.spec.ts b/src/app/shared/services/date.service.spec.ts new file mode 100644 index 00000000..0de8bb21 --- /dev/null +++ b/src/app/shared/services/date.service.spec.ts @@ -0,0 +1,12 @@ +import { DateService } from 'src/app/shared/services/date.service'; + +describe('DateService', () => { + let service: DateService; + beforeEach(() => { + service = new DateService(); + }); + + it('#isInThePast should return true for past date', () => { + expect(service.isInThePast(new Date('1970-01-01'))).toBe(true); + }); +}); diff --git a/src/app/shared/services/date.service.ts b/src/app/shared/services/date.service.ts index 3d248293..87070f2b 100644 --- a/src/app/shared/services/date.service.ts +++ b/src/app/shared/services/date.service.ts @@ -8,7 +8,6 @@ import { Timestamp } from '@firebase/firestore'; }) export class DateService { parseISO = parseISO; - constructor() {} isBetweenDates(date1: Date, date2: Date, dateToCompare: Date): boolean { return compareAsc(date1, dateToCompare) === -1 && compareAsc(dateToCompare, date2) === -1; diff --git a/src/app/shared/services/enrollment-types.service.ts b/src/app/shared/services/enrollment-types.service.ts index db27936a..45679ad7 100644 --- a/src/app/shared/services/enrollment-types.service.ts +++ b/src/app/shared/services/enrollment-types.service.ts @@ -29,8 +29,6 @@ export class EnrollmentTypesService { } } -interface enrollmentTypesList { - [key: number]: { +type enrollmentTypesList = Record; diff --git a/src/app/shared/services/event.ts b/src/app/shared/services/event.ts index aabbff2c..08547c22 100644 --- a/src/app/shared/services/event.ts +++ b/src/app/shared/services/event.ts @@ -1,4 +1,4 @@ -import { Timestamp } from '@firebase/firestore-types'; +import { Timestamp } from '@angular/fire/firestore'; export interface EventItem { name: string; diff --git a/src/app/shared/services/global-constants.service.ts b/src/app/shared/services/global-constants.service.ts index 53649396..d1d01909 100644 --- a/src/app/shared/services/global-constants.service.ts +++ b/src/app/shared/services/global-constants.service.ts @@ -1,5 +1,5 @@ export class GlobalConstantsService { - public static appName: string = 'FCT App'; - public static userDataVersion: string = '1'; - public static nonAmbiguousAlphabetCapitalizedNumbers: string = '2345689ABCDEFGHKMNPQRSTWXYZ'; + public static appName = 'FCT App'; + public static userDataVersion = '1'; + public static nonAmbiguousAlphabetCapitalizedNumbers = '2345689ABCDEFGHKMNPQRSTWXYZ'; } diff --git a/src/app/shared/services/mailto.service.ts b/src/app/shared/services/mailto.service.ts index 006a4714..b996b7a3 100644 --- a/src/app/shared/services/mailto.service.ts +++ b/src/app/shared/services/mailto.service.ts @@ -7,8 +7,6 @@ import { Injectable } from '@angular/core'; providedIn: 'root', }) export class MailtoService { - constructor() {} - compose(value: Mailto): string | void { let link = 'mailto:'; diff --git a/src/app/shared/services/major-event.service.ts b/src/app/shared/services/major-event.service.ts index 9a6dc236..2345b429 100644 --- a/src/app/shared/services/major-event.service.ts +++ b/src/app/shared/services/major-event.service.ts @@ -16,6 +16,7 @@ export class MajorEventsService { const date = Date.now(); return this.afs .collection('majorEvents', (ref) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let query: any = ref; query = query.where('eventStartDate', '>=', startOfDay(date)); return query.orderBy('eventStartDate', 'asc'); @@ -27,6 +28,7 @@ export class MajorEventsService { const date = Date.now(); return this.afs .collection('majorEvents', (ref) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let query: any = ref; query = query.where('eventEndDate', '>=', startOfDay(date)); // TODO: Order by eventStartDate diff --git a/src/app/shared/services/plausible.service.ts b/src/app/shared/services/plausible.service.ts index db76ef76..ef1a013f 100644 --- a/src/app/shared/services/plausible.service.ts +++ b/src/app/shared/services/plausible.service.ts @@ -8,13 +8,12 @@ export class PlausibleLocalService { * This is required by ngx-plausible */ registerPlausible(): void { - // @ts-ignore window.plausible = - // @ts-ignore window.plausible || - function () { - // @ts-ignore - (window.plausible.q = window.plausible.q || []).push(arguments); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function (...args: any) { + // @ts-expect-error - This is defined by Plausible in main.ts + (window.plausible.q = window.plausible.q || []).push(args); }; } } diff --git a/src/app/shared/services/routing/guards.service.ts b/src/app/shared/services/routing/guards.service.ts index 62663b6e..372825e2 100644 --- a/src/app/shared/services/routing/guards.service.ts +++ b/src/app/shared/services/routing/guards.service.ts @@ -10,6 +10,7 @@ import { map } from 'rxjs/operators'; providedIn: 'root', }) export class DevelopmentOnlyGuard { + // eslint-disable-next-line @typescript-eslint/no-unused-vars canActivate(_route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): boolean { return !environment.production; } @@ -27,11 +28,13 @@ export const redirectLoggedInToCalendar = () => redirectLoggedInTo(['calendario' export const caAndGreater = () => pipe( customClaims, - map((claims: { [key: string]: any }) => (claims['role'] as number) < 3000), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + map((claims: Record) => (claims['role'] as number) < 3000) ); export const adminOnly = () => pipe( customClaims, - map((claims: { [key: string]: any }) => (claims['role'] as number) === 1000), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + map((claims: Record) => (claims['role'] as number) === 1000) ); diff --git a/src/app/shared/services/routing/preloading-strategy.service.ts b/src/app/shared/services/routing/preloading-strategy.service.ts index bb99bcf8..33e67370 100644 --- a/src/app/shared/services/routing/preloading-strategy.service.ts +++ b/src/app/shared/services/routing/preloading-strategy.service.ts @@ -6,7 +6,8 @@ import { Observable, of } from 'rxjs'; providedIn: 'root', }) export class PreloadingStrategyService implements PreloadingStrategy { - preload(route: Route, fn: () => Observable): Observable { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + preload(route: Route, fn: () => Observable): Observable { if (route.data && route.data['preload']) { return fn(); } diff --git a/src/app/shared/services/rxjs.service.ts b/src/app/shared/services/rxjs.service.ts index a9da4409..2996796e 100644 --- a/src/app/shared/services/rxjs.service.ts +++ b/src/app/shared/services/rxjs.service.ts @@ -9,5 +9,5 @@ import { filter, Observable, OperatorFunction, pipe, UnaryFunction } from 'rxjs' // Attribution: Simon Williams // https://stackoverflow.com/a/62971842 export function filterNullish(): UnaryFunction, Observable> { - return pipe(filter((x) => x != null) as OperatorFunction); + return pipe(filter((x) => x !== null) as OperatorFunction); } diff --git a/src/app/shared/services/service-worker/update-modal/update-modal.component.ts b/src/app/shared/services/service-worker/update-modal/update-modal.component.ts index b029d949..4789d764 100644 --- a/src/app/shared/services/service-worker/update-modal/update-modal.component.ts +++ b/src/app/shared/services/service-worker/update-modal/update-modal.component.ts @@ -1,17 +1,11 @@ -import { Component, OnInit } from '@angular/core'; -import { IonGrid, IonRow, IonText, IonProgressBar } from "@ionic/angular/standalone"; +import { Component } from '@angular/core'; +import { IonGrid, IonRow, IonText, IonProgressBar } from '@ionic/angular/standalone'; @Component({ - selector: 'app-update-modal', - templateUrl: './update-modal.component.html', - styleUrls: ['./update-modal.component.scss'], - standalone: true, - imports: [IonGrid, IonRow, IonText, IonProgressBar], + selector: 'app-update-modal', + templateUrl: './update-modal.component.html', + styleUrls: ['./update-modal.component.scss'], + standalone: true, + imports: [IonGrid, IonRow, IonText, IonProgressBar], }) -export class UpdateModalComponent implements OnInit { - - constructor() { } - - ngOnInit() { } - -} +export class UpdateModalComponent {} diff --git a/src/app/shared/services/string-management.service.ts b/src/app/shared/services/string-management.service.ts index 29ce2254..b7e68a93 100644 --- a/src/app/shared/services/string-management.service.ts +++ b/src/app/shared/services/string-management.service.ts @@ -4,8 +4,6 @@ import { Injectable } from '@angular/core'; providedIn: 'root', }) export class StringManagementService { - constructor() {} - toUppercase(string: string): string { return string.charAt(0).toUpperCase() + string.slice(1); } diff --git a/src/app/shared/services/weather.service.ts b/src/app/shared/services/weather.service.ts index 0200d6e3..7d3ecad6 100644 --- a/src/app/shared/services/weather.service.ts +++ b/src/app/shared/services/weather.service.ts @@ -107,10 +107,8 @@ export interface WeatherInfo { error?: boolean; } -interface WeatherCodesList { - [key: number]: { +type WeatherCodesList = Record; diff --git a/src/app/tabs/calendar/calendar.page.html b/src/app/tabs/calendar/calendar.page.html index f99dd6e7..314049bd 100644 --- a/src/app/tabs/calendar/calendar.page.html +++ b/src/app/tabs/calendar/calendar.page.html @@ -9,17 +9,17 @@ @if (!this.itemView) { - - - - - - - - - - - + + + + + + + + + + + } Calendário @@ -27,40 +27,38 @@ @if (!this.itemView) { -
-
- - - -
- @for (dowhtml of dowList | keyvalue: originalOrder; track dowhtml) { - -
- {{ getDayFromDate(dowhtml.value.date) }} -
-
- } -
- -
{{ fullDate }}
+
+
+ + + +
+ @for (dowhtml of dowList | keyvalue: originalOrder; track dowhtml) { + +
+ {{ getDayFromDate(dowhtml.value.date) }} +
+
+ }
+ +
{{ fullDate }}
- } - - @if (!this.itemView) { - - } - - @if (this.itemView) { - +
+ } @if (!this.itemView) { + + } @if (this.itemView) { + } diff --git a/src/app/tabs/calendar/calendar.page.ts b/src/app/tabs/calendar/calendar.page.ts index c957f66a..2879f62f 100644 --- a/src/app/tabs/calendar/calendar.page.ts +++ b/src/app/tabs/calendar/calendar.page.ts @@ -1,6 +1,6 @@ // @ts-strict-ignore import { Router } from '@angular/router'; -import { Component, inject } from '@angular/core'; +import { Component, inject, OnInit } from '@angular/core'; import { KeyValue, KeyValuePipe, NgClass, formatDate } from '@angular/common'; import { CoursesService } from 'src/app/shared/services/courses.service'; @@ -23,7 +23,7 @@ import { trace } from '@angular/fire/compat/performance'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { CalendarListViewComponent } from 'src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component'; -import { ItemListViewComponent } from 'src/app/tabs/calendar/components/item-list-view/item-list.component'; +import { ItemListViewComponent } from 'src/app/tabs/calendar/components/item-list-view/item-list-view.component'; @UntilDestroy() @Component({ @@ -45,14 +45,14 @@ import { ItemListViewComponent } from 'src/app/tabs/calendar/components/item-lis NgClass, ], }) -export class CalendarPage { +export class CalendarPage implements OnInit { private remoteConfig: RemoteConfig = inject(RemoteConfig); // Selected calendar date active: string; fullDate: string; - itemView: boolean = true; + itemView = true; selectedFilter: { - courses: Array; + courses: string[]; } = { courses: [], }; @@ -65,7 +65,7 @@ export class CalendarPage { courses = CoursesService.courses; // Limit button clicks - weekClicks: number = 0; + weekClicks = 0; // List of days of week and date dowList = { @@ -106,6 +106,7 @@ export class CalendarPage { this.generateCalendarData(); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars originalOrder = (a: KeyValue, b: KeyValue): number => { return 0; }; @@ -167,7 +168,7 @@ export class CalendarPage { generateCalendarData(): void { let i = 0; - for (let dow in this.dowList) { + for (const dow in this.dowList) { this.dowList[dow].date = addDays(this.calendarBaseDate, i); i++; } diff --git a/src/app/tabs/calendar/calendar.routes.ts b/src/app/tabs/calendar/calendar.routes.ts index 19ac1509..4dd7fa2a 100644 --- a/src/app/tabs/calendar/calendar.routes.ts +++ b/src/app/tabs/calendar/calendar.routes.ts @@ -1,4 +1,4 @@ -import { RouterModule, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { CalendarPage } from './calendar.page'; export const routes: Routes = [ diff --git a/src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component.html b/src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component.html index 133be1ab..b0d133ac 100644 --- a/src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component.html +++ b/src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component.html @@ -1,36 +1,33 @@ @if (items$ | async; as items) { - - Mostrar eventos mais antigos - - @for (item of items; track item; let i = $index) { - @if (i == 0 || !dateService.compareMonthTimestamp(items[i - 1].eventStartDate, items[i].eventStartDate)) { - - {{ formatMonth(dateService.getDateFromTimestamp(item.eventStartDate)) }} - - } - @if (i == 0 || !dateService.compareDayTimestamp(items[i - 1].eventStartDate, items[i].eventStartDate)) { - - - {{ formatDate(dateService.getDateFromTimestamp(item.eventStartDate)) }} - - - } - - } - @if (items.length === 0) { -

Nenhum evento encontrado

- } - } @else { - - - - + + Mostrar eventos mais antigos + + @for (item of items; track item; let i = $index) { @if (i === 0 || !dateService.compareMonthTimestamp(items[i - + 1].eventStartDate, items[i].eventStartDate)) { + + {{ formatMonth(dateService.getDateFromTimestamp(item.eventStartDate)) }} + + } @if (i === 0 || !dateService.compareDayTimestamp(items[i - 1].eventStartDate, items[i].eventStartDate)) { + + + {{ formatDate(dateService.getDateFromTimestamp(item.eventStartDate)) }} + + + } + + } @if (items.length === 0) { +

Nenhum evento encontrado

+ } } @else { + + + + }
diff --git a/src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component.ts b/src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component.ts index 22c4a343..0c3e873c 100644 --- a/src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component.ts +++ b/src/app/tabs/calendar/components/calendar-list-view/calendar-list-view.component.ts @@ -46,15 +46,15 @@ import { ItemListComponent } from 'src/app/tabs/calendar/components/item-list/it }) export class CalendarListViewComponent implements OnInit, OnChanges { @Input() filter: { - courses: Array; + courses: string[]; }; - courseFilter$: BehaviorSubject<{ - courses: Array; - } | null> = new BehaviorSubject(null); - dateFilter$: BehaviorSubject = new BehaviorSubject(null); + courseFilter$ = new BehaviorSubject<{ + courses: string[]; + } | null>(null); + dateFilter$ = new BehaviorSubject(null); - loadOlderCount: number = 0; + loadOlderCount = 0; items$: Observable; @@ -73,6 +73,7 @@ export class CalendarListViewComponent implements OnInit, OnChanges { switchMap(([filter, date]) => { return this.afs .collection('events', (ref) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let query: any = ref; if (date) { query = query.where('eventStartDate', '>=', this.baseDate); @@ -108,7 +109,7 @@ export class CalendarListViewComponent implements OnInit, OnChanges { } loadOlderEvents() { - if (this.loadOlderCount == 0) { + if (this.loadOlderCount === 0) { this.baseDate = startOfWeek(this.baseDate); } @@ -125,7 +126,7 @@ export class CalendarListViewComponent implements OnInit, OnChanges { async presentToast() { const toast = await this.toastController.create({ header: 'Procurando por eventos mais antigos...', - message: 'De até ' + this.loadOlderCount + (this.loadOlderCount == 1 ? ' semana ' : ' semanas ') + 'atrás', + message: 'De até ' + this.loadOlderCount + (this.loadOlderCount === 1 ? ' semana ' : ' semanas ') + 'atrás', icon: 'search', position: 'bottom', duration: 1000, diff --git a/src/app/tabs/calendar/components/filter-modal/filter-modal.page.ts b/src/app/tabs/calendar/components/filter-modal/filter-modal.page.ts index e40eef4d..9e927bf1 100644 --- a/src/app/tabs/calendar/components/filter-modal/filter-modal.page.ts +++ b/src/app/tabs/calendar/components/filter-modal/filter-modal.page.ts @@ -1,6 +1,6 @@ // @ts-strict-ignore import { KeyValue, KeyValuePipe } from '@angular/common'; -import { AfterViewInit, Component, Input, OnInit } from '@angular/core'; +import { AfterViewInit, Component, Input } from '@angular/core'; import { ModalController } from '@ionic/angular/standalone'; import { CoursesService } from 'src/app/shared/services/courses.service'; @@ -38,18 +38,22 @@ import { KeyValuePipe, ], }) -export class FilterModalPage implements OnInit, AfterViewInit { +// TODO: Refactor me, use forms +export class FilterModalPage implements AfterViewInit { courses = CoursesService.courses; constructor(private modalController: ModalController) {} @Input() selectedFilter: { - courses: Array; + courses: string[]; }; ngAfterViewInit() { - const elements: HTMLCollectionOf = document.getElementsByClassName('course'); + const elements: HTMLCollectionOf = document.getElementsByClassName( + 'course' + ) as HTMLCollectionOf; + // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < elements.length; i++) { // Check checkboxes that have id matching selectedFilter if (this.selectedFilter['courses'].includes(elements[i].id)) { @@ -58,10 +62,8 @@ export class FilterModalPage implements OnInit, AfterViewInit { } } - ngOnInit() {} - checkBoxClickCourse(coursekey: string) { - let coursesArray = this.selectedFilter['courses']; + const coursesArray = this.selectedFilter['courses']; // Add coursekey to array if not present. If present, remove it if (coursesArray.includes(coursekey)) { coursesArray.splice(coursesArray.indexOf(coursekey), 1); @@ -72,11 +74,16 @@ export class FilterModalPage implements OnInit, AfterViewInit { } uncheckAll() { // Get elements with course.key id - const elements: HTMLCollectionOf = document.getElementsByClassName('course'); + + const elements: HTMLCollectionOf = document.getElementsByClassName( + 'course' + ) as HTMLCollectionOf; // Uncheck all elements + // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < elements.length; i++) { elements[i].checked = false; } + // Clear all selectedFilter keys this.selectedFilter['courses'] = []; } @@ -88,6 +95,7 @@ export class FilterModalPage implements OnInit, AfterViewInit { }); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars originalOrder = (a: KeyValue, b: KeyValue): number => { return 0; }; diff --git a/src/app/tabs/calendar/components/item-list-view/item-list.component.html b/src/app/tabs/calendar/components/item-list-view/item-list-view.component.html similarity index 100% rename from src/app/tabs/calendar/components/item-list-view/item-list.component.html rename to src/app/tabs/calendar/components/item-list-view/item-list-view.component.html diff --git a/src/app/tabs/calendar/components/item-list-view/item-list.component.scss b/src/app/tabs/calendar/components/item-list-view/item-list-view.component.scss similarity index 100% rename from src/app/tabs/calendar/components/item-list-view/item-list.component.scss rename to src/app/tabs/calendar/components/item-list-view/item-list-view.component.scss diff --git a/src/app/tabs/calendar/components/item-list-view/item-list.component.ts b/src/app/tabs/calendar/components/item-list-view/item-list-view.component.ts similarity index 85% rename from src/app/tabs/calendar/components/item-list-view/item-list.component.ts rename to src/app/tabs/calendar/components/item-list-view/item-list-view.component.ts index 598436de..a3c49650 100644 --- a/src/app/tabs/calendar/components/item-list-view/item-list.component.ts +++ b/src/app/tabs/calendar/components/item-list-view/item-list-view.component.ts @@ -19,9 +19,9 @@ import { ItemListComponent } from 'src/app/tabs/calendar/components/item-list/it import { AsyncPipe } from '@angular/common'; @Component({ - selector: 'app-item-list', - templateUrl: './item-list.component.html', - styleUrls: ['./item-list.component.scss'], + selector: 'app-item-list-view', + templateUrl: './item-list-view.component.html', + styleUrls: ['./item-list-view.component.scss'], standalone: true, imports: [IonList, IonProgressBar, ItemListComponent, AsyncPipe], }) @@ -30,13 +30,13 @@ export class ItemListViewComponent implements OnInit, OnChanges { @Input() date: Date; @Input() filter: { - courses: Array; + courses: string[]; }; - dateFilter$: BehaviorSubject = new BehaviorSubject(null); - courseFilter$: BehaviorSubject<{ - courses: Array; - } | null> = new BehaviorSubject(null); + dateFilter$ = new BehaviorSubject(null); + courseFilter$ = new BehaviorSubject<{ + courses: string[]; + } | null>(null); items$: Observable; @@ -47,6 +47,7 @@ export class ItemListViewComponent implements OnInit, OnChanges { switchMap(([date, filter]) => { return this.afs .collection('events', (ref) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let query: any = ref; if (date) { query = query diff --git a/src/app/tabs/calendar/components/item-list/item-list.component.html b/src/app/tabs/calendar/components/item-list/item-list.component.html index 0af01a26..e71cc813 100644 --- a/src/app/tabs/calendar/components/item-list/item-list.component.html +++ b/src/app/tabs/calendar/components/item-list/item-list.component.html @@ -2,7 +2,13 @@ (click)="openItem(eventItem)" class="item-fake-button" [class]="courses[eventItem.course] ? courses[eventItem.course].color + '-25' : undefined"> - +

{{ eventItem.name }}

diff --git a/src/app/tabs/calendar/components/item-list/item-list.component.ts b/src/app/tabs/calendar/components/item-list/item-list.component.ts index e3cd524b..c079d950 100644 --- a/src/app/tabs/calendar/components/item-list/item-list.component.ts +++ b/src/app/tabs/calendar/components/item-list/item-list.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { EventItem } from '../../../../shared/services/event'; import { EmojiService } from '../../../../shared/services/emoji.service'; import { CoursesService } from 'src/app/shared/services/courses.service'; @@ -19,7 +19,7 @@ import { DatePipe } from '@angular/common'; standalone: true, imports: [IonItem, IonLabel, DatePipe], }) -export class ItemListComponent implements OnInit { +export class ItemListComponent { courses = CoursesService.courses; @Input() @@ -27,8 +27,7 @@ export class ItemListComponent implements OnInit { constructor(public emojiService: EmojiService, private navCtrl: NavController, public dateService: DateService) {} - ngOnInit() {} - + // eslint-disable-next-line @typescript-eslint/no-explicit-any public openItem(item: any): void { this.navCtrl.navigateForward(['calendario/evento', item.id], { state: { item: item }, diff --git a/src/app/tabs/calendar/event-info-display/event-info-display.page.html b/src/app/tabs/calendar/event-info-display/event-info-display.page.html index 9218d152..3707e512 100644 --- a/src/app/tabs/calendar/event-info-display/event-info-display.page.html +++ b/src/app/tabs/calendar/event-info-display/event-info-display.page.html @@ -7,21 +7,21 @@ - - + > + + - - @if (item$ | async; as items) { -
- - - - -
- } @else { - - } -
+ + @if (item$ | async; as items) { +
+ + + + +
+ } @else { + + } +
diff --git a/src/app/tabs/calendar/event-info-display/event-info-display.page.ts b/src/app/tabs/calendar/event-info-display/event-info-display.page.ts index 1f1ca8c0..4d45030a 100644 --- a/src/app/tabs/calendar/event-info-display/event-info-display.page.ts +++ b/src/app/tabs/calendar/event-info-display/event-info-display.page.ts @@ -8,7 +8,7 @@ import { ToastController } from '@ionic/angular/standalone'; import { ActivatedRoute, Router } from '@angular/router'; import { EventItem } from '../../../shared/services/event'; -import { take, Observable, map } from 'rxjs'; +import { Observable } from 'rxjs'; import { trace } from '@angular/fire/compat/performance'; import { AngularFirestore } from '@angular/fire/compat/firestore'; @@ -24,8 +24,8 @@ import { IonProgressBar, } from '@ionic/angular/standalone'; import { AsyncPipe } from '@angular/common'; -import { HeaderComponent } from 'src/app/shared/components/event-display/header/header.component'; -import { DescriptionComponent } from 'src/app/shared/components/event-display/description/description.component'; +import { EventHeaderComponent } from 'src/app/shared/components/event-display/event-header/event-header.component'; +import { EventDescriptionComponent } from 'src/app/shared/components/event-display/event-description/event-description.component'; import { MapComponent } from 'src/app/shared/components/event-display/map/map.component'; import { ButtonsComponent } from 'src/app/shared/components/event-display/buttons/buttons.component'; import { environment } from 'src/environments/environment'; @@ -47,8 +47,8 @@ import { PlausibleService } from '@notiz/ngx-plausible'; IonContent, IonProgressBar, AsyncPipe, - HeaderComponent, - DescriptionComponent, + EventHeaderComponent, + EventDescriptionComponent, MapComponent, ButtonsComponent, ], @@ -64,7 +64,7 @@ export class EventInfoDisplayPage implements OnInit { private toastController: ToastController, private router: Router, private route: ActivatedRoute, - private afs: AngularFirestore, + private afs: AngularFirestore ) {} ngOnInit() { diff --git a/src/app/tabs/calendar/event-info-display/event-info-display.routes.ts b/src/app/tabs/calendar/event-info-display/event-info-display.routes.ts index b77533a9..e7060ce4 100644 --- a/src/app/tabs/calendar/event-info-display/event-info-display.routes.ts +++ b/src/app/tabs/calendar/event-info-display/event-info-display.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { EventInfoDisplayPage } from './event-info-display.page'; diff --git a/src/app/tabs/major-events-display/major-events-display.page.html b/src/app/tabs/major-events-display/major-events-display.page.html index 5e57f656..cb509862 100644 --- a/src/app/tabs/major-events-display/major-events-display.page.html +++ b/src/app/tabs/major-events-display/major-events-display.page.html @@ -5,42 +5,36 @@ - @if (majorEvents$ | async; as majorEventsList) { - @if (majorEventsList.length === 0) { -

Nenhum evento disponível

- } - @if (majorEventsList.length > 0) { -
- @for (event of majorEventsList; track event) { - - - - - -
- @if ((event.subscriptionStartDate && event.subscriptionEndDate) && isTodayBetweenDates(dateService.getDateFromTimestamp(event.subscriptionStartDate), dateService.getDateFromTimestamp(event.subscriptionEndDate))) { - @if (event.isSubscribed | async; as isSubscribed) { - @if (isSubscribed) { - - Inscrito - - } - } @else { - Inscreva-se - } - } - @if (event.button?.url) { - - {{ event.button.text || 'Saiba mais' }} - - } -
-
+ @if (majorEvents$ | async; as majorEventsList) { @if (majorEventsList.length === 0) { +

Nenhum evento disponível

+ } @if (majorEventsList.length > 0) { +
+ @for (event of majorEventsList; track event) { + + + + + +
+ @if ((event.subscriptionStartDate && event.subscriptionEndDate) && + isTodayBetweenDates(dateService.getDateFromTimestamp(event.subscriptionStartDate), + dateService.getDateFromTimestamp(event.subscriptionEndDate))) { @if (event.isSubscribed | async; as + isSubscribed) { @if (isSubscribed) { + + Inscrito + + } } @else { + Inscreva-se + } } @if (event.button?.url) { + + {{ event.button.text || 'Saiba mais' }} + }
+
} - } @else { - +
+ } } @else { + } - diff --git a/src/app/tabs/major-events-display/major-events-display.page.ts b/src/app/tabs/major-events-display/major-events-display.page.ts index 2fd60749..b9689fad 100644 --- a/src/app/tabs/major-events-display/major-events-display.page.ts +++ b/src/app/tabs/major-events-display/major-events-display.page.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { Component, inject } from '@angular/core'; +import { Component, inject, OnInit } from '@angular/core'; import { AngularFirestore } from '@angular/fire/compat/firestore'; import { trace } from '@angular/fire/compat/performance'; import { compareAsc, subMonths, startOfDay } from 'date-fns'; @@ -24,8 +24,8 @@ import { IonRouterLink, } from '@ionic/angular/standalone'; import { RouterLink } from '@angular/router'; -import { HeaderComponent } from 'src/app/shared/components/major-event-display/header/header.component'; -import { DescriptionComponent } from 'src/app/shared/components/major-event-display/description/description.component'; +import { MajorEventHeaderComponent } from 'src/app/shared/components/major-event-display/major-event-header/major-event-header.component'; +import { MajorEventDescriptionComponent } from 'src/app/shared/components/major-event-display/major-event-description/major-event-description.component'; import { DateComponent } from 'src/app/shared/components/major-event-display/date/date.component'; import { PriceComponent } from 'src/app/shared/components/major-event-display/price/price.component'; @@ -46,13 +46,13 @@ import { PriceComponent } from 'src/app/shared/components/major-event-display/pr IonProgressBar, RouterLink, IonRouterLink, - HeaderComponent, - DescriptionComponent, + MajorEventHeaderComponent, + MajorEventDescriptionComponent, DateComponent, PriceComponent, ], }) -export class MajorEventsDisplayPage { +export class MajorEventsDisplayPage implements OnInit { private auth: Auth = inject(Auth); user$ = user(this.auth); @@ -63,15 +63,13 @@ export class MajorEventsDisplayPage { >; today: Date = new Date(); - constructor( - public afs: AngularFirestore, - public dateService: DateService, - ) {} + constructor(public afs: AngularFirestore, public dateService: DateService) {} ngOnInit() { this.user$.pipe(take(1)).subscribe((user) => { this.majorEvents$ = this.afs .collection('majorEvents', (ref) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any let query: any = ref; // TODO: Show events in which the subscription opens in the next 2 weeks AND events that ended in the last 2 weeks @@ -100,12 +98,12 @@ export class MajorEventsDisplayPage { } } return doc.exists; - }), + }) ) : null, }; }); - }), + }) ); }); } diff --git a/src/app/tabs/major-events-display/major-events-display.routes.ts b/src/app/tabs/major-events-display/major-events-display.routes.ts index 1938018d..ac96700c 100644 --- a/src/app/tabs/major-events-display/major-events-display.routes.ts +++ b/src/app/tabs/major-events-display/major-events-display.routes.ts @@ -1,4 +1,4 @@ -import { RouterModule, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { MajorEventsDisplayPage } from './major-events-display.page'; export const routes: Routes = [ diff --git a/src/app/tabs/major-events-display/subscribe/confirm-modal/confirm-modal.component.html b/src/app/tabs/major-events-display/subscribe/confirm-modal/confirm-modal.component.html deleted file mode 100644 index d8d2add2..00000000 --- a/src/app/tabs/major-events-display/subscribe/confirm-modal/confirm-modal.component.html +++ /dev/null @@ -1,147 +0,0 @@ - - - Confirmar inscrição - - Cancelar - - - - - -
- @if (majorEvent$ | async; as majorEvent) { - - {{ majorEvent.name }} - - @if (majorEvent.description) { - -

{{ majorEvent.description }}

-
- } -
-
- - Datas -
- - Evento - - {{ dateService.getDateFromTimestamp(majorEvent.eventStartDate) | date: 'dd/MM' }} - {{ - majorEvent.eventEndDate && - '- ' + (dateService.getDateFromTimestamp(majorEvent.eventEndDate) | date: 'dd/MM') - }} - - - @if (majorEvent.subscriptionStartDate && majorEvent.subscriptionEndDate) { - - Inscrição - - {{ dateService.getDateFromTimestamp(majorEvent.subscriptionStartDate) | date: 'dd/MM' }} - {{ - majorEvent.subscriptionEndDate && - '- ' + (dateService.getDateFromTimestamp(majorEvent.subscriptionEndDate) | date: 'dd/MM') - }} - - - } -
- @if (majorEvent.price) { -
-
- - Valores -
- @if (majorEvent.price.isFree) { - - Gratuito - - } @else { - @if (majorEvent.price.single) { - - Preço único - {{ majorEvent.price.single | currency: 'BRL' }} - - } @else { - @if (subscriptionType === '0' && majorEvent.price.students) { - - {{ enrollmentTypes.getEnrollmentType(0) }} - {{ majorEvent.price.students | currency: 'BRL' }} - - } - @if (subscriptionType === '1' && majorEvent.price.otherStudents) { - - {{ enrollmentTypes.getEnrollmentType(1) }} - {{ majorEvent.price.otherStudents | currency: 'BRL' }} - - } - @if (subscriptionType === '2' && majorEvent.price.professors) { - - {{ enrollmentTypes.getEnrollmentType(2) }} - {{ majorEvent.price.professors | currency: 'BRL' }} - - } - } - } -
- } -
-

- {{ minicursosCount | number: '2.0-0' }} de {{ majorEvent.maxCourses | number: '2.0-0' }} minicursos - selecionados -

-

- {{ palestrasCount | number: '2.0-0' }} de {{ majorEvent.maxLectures | number: '2.0-0' }} palestras - selecionados -

-
- } @else { - - } - - @if (eventsSelected; as eventsArray) { - @for (event of eventsArray; track event; let i = $index) { - @if (i == 0 || !dateService.compareDayTimestamp(eventsArray[i - 1].eventStartDate, event.eventStartDate)) { - - {{ formatDate(dateService.getDateFromTimestamp(event.eventStartDate)) }} - - } - - - - -

{{ event.name }}

-

- {{ dateService.getDateFromTimestamp(event.eventStartDate) | date: 'HH:mm' }} - {{ - event.eventEndDate && ' às ' + (dateService.getDateFromTimestamp(event.eventEndDate) | date: 'HH:mm') - }} -

-
-
-
- } - } - - Confirmar -
- - - - -
- - diff --git a/src/app/tabs/major-events-display/subscribe/confirm-subscription-modal/confirm-subscription-modal.component.html b/src/app/tabs/major-events-display/subscribe/confirm-subscription-modal/confirm-subscription-modal.component.html new file mode 100644 index 00000000..9a532405 --- /dev/null +++ b/src/app/tabs/major-events-display/subscribe/confirm-subscription-modal/confirm-subscription-modal.component.html @@ -0,0 +1,136 @@ + + + Confirmar inscrição + + Cancelar + + + + + +
+ @if (majorEvent$ | async; as majorEvent) { + + {{ majorEvent.name }} + + @if (majorEvent.description) { + +

{{ majorEvent.description }}

+
+ } +
+
+ + Datas +
+ + Evento + + {{ dateService.getDateFromTimestamp(majorEvent.eventStartDate) | date : 'dd/MM' }} + {{ + majorEvent.eventEndDate && + '- ' + (dateService.getDateFromTimestamp(majorEvent.eventEndDate) | date : 'dd/MM') + }} + + + @if (majorEvent.subscriptionStartDate && majorEvent.subscriptionEndDate) { + + Inscrição + + {{ dateService.getDateFromTimestamp(majorEvent.subscriptionStartDate) | date : 'dd/MM' }} + {{ + majorEvent.subscriptionEndDate && + '- ' + (dateService.getDateFromTimestamp(majorEvent.subscriptionEndDate) | date : 'dd/MM') + }} + + + } +
+ @if (majorEvent.price) { +
+
+ + Valores +
+ @if (majorEvent.price.isFree) { + + Gratuito + + } @else { @if (majorEvent.price.single) { + + Preço único + {{ majorEvent.price.single | currency : 'BRL' }} + + } @else { @if (subscriptionType === '0' && majorEvent.price.students) { + + {{ enrollmentTypes.getEnrollmentType(0) }} + {{ majorEvent.price.students | currency : 'BRL' }} + + } @if (subscriptionType === '1' && majorEvent.price.otherStudents) { + + {{ enrollmentTypes.getEnrollmentType(1) }} + {{ majorEvent.price.otherStudents | currency : 'BRL' }} + + } @if (subscriptionType === '2' && majorEvent.price.professors) { + + {{ enrollmentTypes.getEnrollmentType(2) }} + {{ majorEvent.price.professors | currency : 'BRL' }} + + } } } +
+ } +
+

+ {{ minicursosCount | number : '2.0-0' }} de {{ majorEvent.maxCourses | number : '2.0-0' }} minicursos + selecionados +

+

+ {{ palestrasCount | number : '2.0-0' }} de {{ majorEvent.maxLectures | number : '2.0-0' }} palestras + selecionados +

+
+ } @else { + + } @if (eventsSelected; as eventsArray) { @for (event of eventsArray; track event; let i = $index) { @if (i === 0 || + !dateService.compareDayTimestamp(eventsArray[i - 1].eventStartDate, event.eventStartDate)) { + + {{ formatDate(dateService.getDateFromTimestamp(event.eventStartDate)) }} + + } + + + + +

{{ event.name }}

+

+ {{ dateService.getDateFromTimestamp(event.eventStartDate) | date : 'HH:mm' }} + {{ event.eventEndDate && ' às ' + (dateService.getDateFromTimestamp(event.eventEndDate) | date : 'HH:mm') }} +

+
+
+
+ } } + + Confirmar +
+ + + + +
+ + diff --git a/src/app/tabs/major-events-display/subscribe/confirm-modal/confirm-modal.component.scss b/src/app/tabs/major-events-display/subscribe/confirm-subscription-modal/confirm-subscription-modal.component.scss similarity index 100% rename from src/app/tabs/major-events-display/subscribe/confirm-modal/confirm-modal.component.scss rename to src/app/tabs/major-events-display/subscribe/confirm-subscription-modal/confirm-subscription-modal.component.scss diff --git a/src/app/tabs/major-events-display/subscribe/confirm-modal/confirm-modal.component.ts b/src/app/tabs/major-events-display/subscribe/confirm-subscription-modal/confirm-subscription-modal.component.ts similarity index 87% rename from src/app/tabs/major-events-display/subscribe/confirm-modal/confirm-modal.component.ts rename to src/app/tabs/major-events-display/subscribe/confirm-subscription-modal/confirm-subscription-modal.component.ts index c3de6f16..165f6b3d 100644 --- a/src/app/tabs/major-events-display/subscribe/confirm-modal/confirm-modal.component.ts +++ b/src/app/tabs/major-events-display/subscribe/confirm-subscription-modal/confirm-subscription-modal.component.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { AngularFirestore } from '@angular/fire/compat/firestore'; import { AsyncPipe, CurrencyPipe, DatePipe, DecimalPipe, formatDate } from '@angular/common'; @@ -32,9 +32,9 @@ import { import { SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2'; @Component({ - selector: 'app-confirm-modal', - templateUrl: './confirm-modal.component.html', - styleUrls: ['./confirm-modal.component.scss'], + selector: 'app-confirm-subscription-modal', + templateUrl: './confirm-subscription-modal.component.html', + styleUrls: ['./confirm-subscription-modal.component.scss'], standalone: true, imports: [ IonHeader, @@ -59,7 +59,7 @@ import { SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2'; DatePipe, ], }) -export class ConfirmModalComponent implements OnInit { +export class ConfirmSubscriptionModalComponent { @Input() majorEvent$: Observable; @Input() eventsSelected: EventItem[]; @Input() minicursosCount: number; @@ -71,11 +71,9 @@ export class ConfirmModalComponent implements OnInit { private modalController: ModalController, public enrollmentTypes: EnrollmentTypesService, public emojiService: EmojiService, - public dateService: DateService + public dateService: DateService, ) {} - ngOnInit() {} - formatDate(date: Date): string { let formated = formatDate(date, "EEEE, dd 'de' MMMM 'de' yyyy", 'pt-BR'); diff --git a/src/app/tabs/major-events-display/subscribe/info-modal/info-modal.component.html b/src/app/tabs/major-events-display/subscribe/info-modal/info-modal.component.html index 6b53c464..8229fe24 100644 --- a/src/app/tabs/major-events-display/subscribe/info-modal/info-modal.component.html +++ b/src/app/tabs/major-events-display/subscribe/info-modal/info-modal.component.html @@ -10,7 +10,7 @@
- - + +
diff --git a/src/app/tabs/major-events-display/subscribe/info-modal/info-modal.component.ts b/src/app/tabs/major-events-display/subscribe/info-modal/info-modal.component.ts index e7dd83f8..cd5afb92 100644 --- a/src/app/tabs/major-events-display/subscribe/info-modal/info-modal.component.ts +++ b/src/app/tabs/major-events-display/subscribe/info-modal/info-modal.component.ts @@ -1,9 +1,9 @@ // @ts-strict-ignore import { ModalController } from '@ionic/angular/standalone'; -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { EventItem } from 'src/app/shared/services/event'; -import { DescriptionComponent } from '../../../../shared/components/event-display/description/description.component'; -import { HeaderComponent } from '../../../../shared/components/event-display/header/header.component'; +import { EventDescriptionComponent } from '../../../../shared/components/event-display/event-description/event-description.component'; +import { EventHeaderComponent } from '../../../../shared/components/event-display/event-header/event-header.component'; import { addIcons } from 'ionicons'; import { closeOutline } from 'ionicons/icons'; import { IonHeader, IonToolbar, IonButtons, IonButton, IonIcon, IonTitle, IonContent } from '@ionic/angular/standalone'; @@ -14,8 +14,8 @@ import { IonHeader, IonToolbar, IonButtons, IonButton, IonIcon, IonTitle, IonCon styleUrls: ['./info-modal.component.scss'], standalone: true, imports: [ - HeaderComponent, - DescriptionComponent, + EventHeaderComponent, + EventDescriptionComponent, IonHeader, IonToolbar, IonButtons, @@ -25,15 +25,13 @@ import { IonHeader, IonToolbar, IonButtons, IonButton, IonIcon, IonTitle, IonCon IonContent, ], }) -export class InfoModalComponent implements OnInit { +export class InfoModalComponent { @Input() event: EventItem; constructor(private modalController: ModalController) { addIcons({ closeOutline }); } - ngOnInit() {} - closeModal() { this.modalController.dismiss(); } diff --git a/src/app/tabs/major-events-display/subscribe/subscribe.page.html b/src/app/tabs/major-events-display/subscribe/subscribe.page.html index b9cdb561..9f85c56c 100644 --- a/src/app/tabs/major-events-display/subscribe/subscribe.page.html +++ b/src/app/tabs/major-events-display/subscribe/subscribe.page.html @@ -116,7 +116,7 @@

- @if (events$ | async; as eventsArray) { @for (event of eventsArray; track event; let i = $index) { @if (i == 0 || + @if (events$ | async; as eventsArray) { @for (event of eventsArray; track event; let i = $index) { @if (i === 0 || !dateService.compareDayTimestamp(eventsArray[i - 1].eventStartDate, event.eventStartDate)) { {{ formatDate(dateService.getDateFromTimestamp(event.eventStartDate)) }} @@ -127,6 +127,7 @@ diff --git a/src/app/tabs/major-events-display/subscribe/subscribe.page.ts b/src/app/tabs/major-events-display/subscribe/subscribe.page.ts index 3ce67691..0cccd886 100644 --- a/src/app/tabs/major-events-display/subscribe/subscribe.page.ts +++ b/src/app/tabs/major-events-display/subscribe/subscribe.page.ts @@ -16,7 +16,7 @@ import { MajorEventItem } from 'src/app/shared/services/major-event.service'; import { EventItem } from 'src/app/shared/services/event'; import { ModalController, ToastController } from '@ionic/angular/standalone'; -import { ConfirmModalComponent } from './confirm-modal/confirm-modal.component'; +import { ConfirmSubscriptionModalComponent } from './confirm-subscription-modal/confirm-subscription-modal.component'; import { SwalComponent, SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2'; import { trace } from '@angular/fire/compat/performance'; @@ -116,12 +116,12 @@ export class SubscribePage implements OnInit { dataForm: FormGroup; - eventsSelected: { [key: string]: EventItem[] } = { + eventsSelected: Record = { minicurso: [], palestra: [], }; - eventGroupMinicursoCount: number = 0; + eventGroupMinicursoCount = 0; opSelected: string; @@ -130,7 +130,7 @@ export class SubscribePage implements OnInit { majorEventID: string; eventSchedule: EventItem[] = []; - isEventScheduleBeingChecked: boolean = false; + isEventScheduleBeingChecked = false; constructor( private route: ActivatedRoute, @@ -329,6 +329,7 @@ export class SubscribePage implements OnInit { ); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any countCheckeds(e: any, event: EventItem) { const checked: boolean = e.currentTarget.checked; const name: string = e.currentTarget.name; @@ -478,7 +479,7 @@ export class SubscribePage implements OnInit { .doc(`users/${user.uid}/majorEventSubscriptions/${this.majorEventID}`) .valueChanges({ idField: 'id' }) .pipe(take(1), trace('firestore')) - .subscribe((subscription) => { + .subscribe(() => { if (this.paymentStatus !== 2) { // Merge eventsSelected arrays const eventsSelected = Object.values(this.eventsSelected).reduce((acc, val) => acc.concat(val), []); @@ -486,7 +487,7 @@ export class SubscribePage implements OnInit { // Create array with event IDs from eventsSelected const eventsSelectedID = eventsSelected.map((event) => event.id); - let status: number = 0; + let status = 0; if (this.paymentStatus !== undefined) { switch (this.paymentStatus) { @@ -524,7 +525,7 @@ export class SubscribePage implements OnInit { .collection(`majorEvents/${this.majorEventID}/subscriptions`) .doc(user.uid) .get() - .subscribe((doc) => { + .subscribe(() => { if (status === 0) { this.afs .collection(`majorEvents/${this.majorEventID}/subscriptions`) @@ -532,12 +533,12 @@ export class SubscribePage implements OnInit { .set({ subscriptionType: subscriptionType, subscribedToEvents: eventsSelectedID, - // @ts-ignore + // @ts-expect-error - This works time: serverTimestamp(), payment: { price: price, status: status, - // @ts-ignore + // @ts-expect-error - This works time: serverTimestamp(), author: user.uid, }, @@ -552,7 +553,7 @@ export class SubscribePage implements OnInit { payment: { price: price, status: status, - // @ts-ignore + // @ts-expect-error - This works time: serverTimestamp(), author: user.uid, }, @@ -611,7 +612,7 @@ export class SubscribePage implements OnInit { }); const modal = await this.modalController.create({ - component: ConfirmModalComponent, + component: ConfirmSubscriptionModalComponent, componentProps: { majorEvent$: this.majorEvent$, eventsSelected: eventsSelected, @@ -782,5 +783,6 @@ export class SubscribePage implements OnInit { interface Subscription { id?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any reference?: DocumentReference; } diff --git a/src/app/tabs/major-events-display/subscribe/subscribe.routes.ts b/src/app/tabs/major-events-display/subscribe/subscribe.routes.ts index b7986597..ff44aa50 100644 --- a/src/app/tabs/major-events-display/subscribe/subscribe.routes.ts +++ b/src/app/tabs/major-events-display/subscribe/subscribe.routes.ts @@ -1,4 +1,4 @@ -import { RouterModule, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { SubscribePage } from './subscribe.page'; export const routes: Routes = [ diff --git a/src/app/tabs/map/map.page.ts b/src/app/tabs/map/map.page.ts index b6c55d35..b68e4f32 100644 --- a/src/app/tabs/map/map.page.ts +++ b/src/app/tabs/map/map.page.ts @@ -1,51 +1,48 @@ -import { AfterViewInit, Component, OnInit } from '@angular/core'; +import { AfterViewInit, Component, OnDestroy } from '@angular/core'; import Map from 'ol/Map'; import View from 'ol/View'; import TileLayer from 'ol/layer/Tile'; import OSM from 'ol/source/OSM'; import { useGeographic } from 'ol/proj'; -import { Control, defaults as defaultControls } from 'ol/control'; -import { IonHeader, IonContent } from "@ionic/angular/standalone"; +import { IonHeader, IonContent } from '@ionic/angular/standalone'; useGeographic(); @Component({ - selector: 'app-map', - templateUrl: 'map.page.html', - styleUrls: ['map.page.scss'], - standalone: true, - imports: [IonHeader, IonContent], + selector: 'app-map', + templateUrl: 'map.page.html', + styleUrls: ['map.page.scss'], + standalone: true, + imports: [IonHeader, IonContent], }) -export class MapPage implements AfterViewInit { - map: Map | undefined | null; +export class MapPage implements AfterViewInit, OnDestroy { + map: Map | undefined | null; - constructor() { } + ngAfterViewInit() { + useGeographic(); + const rasterLayer = new TileLayer({ + source: new OSM(), + }); - ngAfterViewInit() { - useGeographic(); - const rasterLayer = new TileLayer({ - source: new OSM(), - }); + setTimeout(() => { + this.map = new Map({ + view: new View({ + center: [-51.40775, -22.12103], + zoom: 18, + maxZoom: 19, + projection: 'EPSG:3857', + }), + layers: [rasterLayer], + target: 'ol-map-tab', + }); + }, 500); + } - setTimeout(() => { - this.map = new Map({ - view: new View({ - center: [-51.40775, -22.12103], - zoom: 18, - maxZoom: 19, - projection: 'EPSG:3857', - }), - layers: [rasterLayer], - target: 'ol-map-tab', - }); - }, 500); - } - - ngOnDestroy() { - // Remove map on leave if it exists - if (this.map) { - this.map.setTarget(undefined); - this.map = null; - } + ngOnDestroy() { + // Remove map on leave if it exists + if (this.map) { + this.map.setTarget(undefined); + this.map = null; } + } } diff --git a/src/app/tabs/map/map.routes.ts b/src/app/tabs/map/map.routes.ts index b0cf677f..9a8e8abd 100644 --- a/src/app/tabs/map/map.routes.ts +++ b/src/app/tabs/map/map.routes.ts @@ -1,4 +1,4 @@ -import { RouterModule, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { MapPage } from './map.page'; export const routes: Routes = [ diff --git a/src/app/tabs/menu/menu.page.html b/src/app/tabs/menu/menu.page.html index 353d8b50..0690174f 100644 --- a/src/app/tabs/menu/menu.page.html +++ b/src/app/tabs/menu/menu.page.html @@ -12,7 +12,7 @@ - + Avatar do usuário

{{userData().displayName}}

@@ -21,7 +21,7 @@ @@ -46,7 +46,7 @@

Entrar

diff --git a/src/app/tabs/menu/menu.page.ts b/src/app/tabs/menu/menu.page.ts index f3560c95..011955cd 100644 --- a/src/app/tabs/menu/menu.page.ts +++ b/src/app/tabs/menu/menu.page.ts @@ -1,4 +1,4 @@ -import { Component, inject, signal, WritableSignal } from '@angular/core'; +import { Component, inject, signal, WritableSignal, OnInit } from '@angular/core'; import { AuthService } from '../../shared/services/auth.service'; @@ -28,7 +28,7 @@ import { IonAvatar, } from '@ionic/angular/standalone'; import { RouterLink } from '@angular/router'; -import { ClickStopPropagation } from 'src/app/shared/directives/click-stop-propagation'; +import { ClickStopPropagationDirective } from 'src/app/shared/directives/click-stop-propagation'; @UntilDestroy() @Component({ @@ -54,10 +54,10 @@ import { ClickStopPropagation } from 'src/app/shared/directives/click-stop-propa IonGrid, IonCol, IonRow, - ClickStopPropagation, + ClickStopPropagationDirective, ], }) -export class MenuPage { +export class MenuPage implements OnInit { private auth: Auth = inject(Auth); user$ = user(this.auth); authState$ = authState(this.auth); diff --git a/src/app/tabs/menu/menu.routes.ts b/src/app/tabs/menu/menu.routes.ts index 1ef0408e..0c9ebe58 100644 --- a/src/app/tabs/menu/menu.routes.ts +++ b/src/app/tabs/menu/menu.routes.ts @@ -1,4 +1,4 @@ -import { RouterModule, Routes } from '@angular/router'; +import { Routes } from '@angular/router'; import { MenuPage } from './menu.page'; export const routes: Routes = [ diff --git a/src/app/unused/page-impersonate/page-impersonate.page.ts b/src/app/unused/page-impersonate/page-impersonate.page.ts index 8ad2019a..78c319fc 100644 --- a/src/app/unused/page-impersonate/page-impersonate.page.ts +++ b/src/app/unused/page-impersonate/page-impersonate.page.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { Component, inject, OnInit } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { Auth, signInWithCustomToken } from '@angular/fire/auth'; import { FormGroup, FormBuilder, ReactiveFormsModule } from '@angular/forms'; import { ToastController } from '@ionic/angular/standalone'; @@ -43,19 +43,20 @@ import { IonButton, ], }) -export class PageImpersonatePage implements OnInit { +export class PageImpersonatePage { impersonateForm: FormGroup; private auth: Auth = inject(Auth); private functions: Functions = inject(Functions); - constructor(private formBuilder: FormBuilder, private toastController: ToastController) { + constructor( + private formBuilder: FormBuilder, + private toastController: ToastController, + ) { this.impersonateForm = this.formBuilder.group({ userID: '', }); } - ngOnInit() {} - impersonate() { const impersonate = httpsCallable(this.functions, 'impersonate'); impersonate({ uid: this.impersonateForm.get('userID').value }).then((res) => { diff --git a/src/app/unused/page-impersonate/page-impersonate.routes.ts b/src/app/unused/page-impersonate/page-impersonate.routes.ts index 043a8d8d..20065e59 100644 --- a/src/app/unused/page-impersonate/page-impersonate.routes.ts +++ b/src/app/unused/page-impersonate/page-impersonate.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { PageImpersonatePage } from './page-impersonate.page'; diff --git a/src/app/unused/page-qr-scanner-public/page-qr-scanner.page.ts b/src/app/unused/page-qr-scanner-public/page-qr-scanner.page.ts index eacd0b09..3eb8e0c7 100644 --- a/src/app/unused/page-qr-scanner-public/page-qr-scanner.page.ts +++ b/src/app/unused/page-qr-scanner-public/page-qr-scanner.page.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { BarcodeFormat } from '@zxing/library'; import { BehaviorSubject } from 'rxjs'; import { ModalController } from '@ionic/angular/standalone'; @@ -39,11 +39,11 @@ import { IonIcon, ], }) -export class PageQrScannerPage implements OnInit { +export class PageQrScannerPage { constructor( public modalController: ModalController, private routerOutlet: IonRouterOutlet, - public toastController: ToastController + public toastController: ToastController, ) {} availableDevices: MediaDeviceInfo[]; currentDevice: MediaDeviceInfo = null; @@ -76,7 +76,6 @@ export class PageQrScannerPage implements OnInit { return await modal.present(); } */ - ngOnInit() {} changeCamera(): void { this.deviceIndex++; diff --git a/src/app/unused/page-qr-scanner-public/page-qr-scanner.routes.ts b/src/app/unused/page-qr-scanner-public/page-qr-scanner.routes.ts index cc81e21e..3457526f 100644 --- a/src/app/unused/page-qr-scanner-public/page-qr-scanner.routes.ts +++ b/src/app/unused/page-qr-scanner-public/page-qr-scanner.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { PageQrScannerPage } from './page-qr-scanner.page'; diff --git a/src/app/unused/verify-phone/verify-phone.routes.ts b/src/app/unused/verify-phone/verify-phone.routes.ts index 8abbc76b..e3d40dea 100644 --- a/src/app/unused/verify-phone/verify-phone.routes.ts +++ b/src/app/unused/verify-phone/verify-phone.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { VerifyPhonePage } from './verify-phone.page'; diff --git a/src/app/validate-certificate/validate-certificate.page.ts b/src/app/validate-certificate/validate-certificate.page.ts index eef2e491..88d3bab7 100644 --- a/src/app/validate-certificate/validate-certificate.page.ts +++ b/src/app/validate-certificate/validate-certificate.page.ts @@ -1,6 +1,6 @@ import { AngularFirestore } from '@angular/fire/compat/firestore'; import { ActivatedRoute } from '@angular/router'; -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { CertificateDocPublic } from 'src/app/shared/services/certificates.service'; import { decodeCertificateCode } from 'src/app/shared/services/certificates.service'; @@ -38,14 +38,17 @@ import { AsyncPipe } from '@angular/common'; AsyncPipe, ], }) -export class ValidateCertificatePage implements OnInit { +export class ValidateCertificatePage { param: string; eventID: string; certificateID: string; certificateDoc: string; certificatePublic$: Observable; - constructor(private route: ActivatedRoute, private afs: AngularFirestore) { + constructor( + private route: ActivatedRoute, + private afs: AngularFirestore, + ) { this.param = this.route.snapshot.paramMap.get('param') as string; const object = decodeCertificateCode(this.param); @@ -61,6 +64,4 @@ export class ValidateCertificatePage implements OnInit { .doc(`certificates/${this.eventID}/${this.certificateID}/${this.certificateDoc}`) .valueChanges({ idField: 'id' }); } - - ngOnInit() {} } diff --git a/src/app/validate-certificate/validate-certificate.routes.ts b/src/app/validate-certificate/validate-certificate.routes.ts index c93e4dec..43cce012 100644 --- a/src/app/validate-certificate/validate-certificate.routes.ts +++ b/src/app/validate-certificate/validate-certificate.routes.ts @@ -1,4 +1,4 @@ -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { ValidateCertificatePage } from './validate-certificate.page'; diff --git a/src/main.ts b/src/main.ts index 82fd8536..86022920 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,13 +11,13 @@ import { AppComponent } from './app/app.component'; import { provideFirestore, initializeFirestore, - persistentLocalCache, - persistentMultipleTabManager, + //persistentLocalCache, + //persistentMultipleTabManager, connectFirestoreEmulator, } from '@angular/fire/firestore'; import { provideFunctions, getFunctions, connectFunctionsEmulator } from '@angular/fire/functions'; import { provideStorage, getStorage, connectStorageEmulator } from '@angular/fire/storage'; -import { GlobalConstantsService } from './app/shared/services/global-constants.service'; + import { provideAuth, getAuth, useDeviceLanguage, connectAuthEmulator } from '@angular/fire/auth'; import { provideRemoteConfig, getRemoteConfig, fetchAndActivate } from '@angular/fire/remote-config'; import { getApp, provideFirebaseApp, initializeApp } from '@angular/fire/app'; @@ -176,7 +176,7 @@ function fetchNonce(): string { const message = 'Ocorreu um erro ao validar a integridade do aplicativo.\nRecarregue a página.\nErro: Nonce não encontrado'; - // @ts-ignore + // @ts-expect-error - Alert is globally available in the browser if (!alert(message)) { window.location.reload(); } diff --git a/tests/example.spec.ts b/tests/example.spec.ts new file mode 100644 index 00000000..88814dcb --- /dev/null +++ b/tests/example.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('https://fctapp.yudi.me/'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/FCT App/); +}); diff --git a/tsconfig.spec.json b/tsconfig.spec.json index b0542260..3a43d7f4 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -1,12 +1,11 @@ /* To learn more about this file see: https://angular.io/config/tsconfig. */ + { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", - "types": [] + "types": ["jasmine"] }, - "include": [ - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] + "include": ["src/**/*.spec.ts", "src/**/*.d.ts"], + "exclude": ["src/app/unused/**/*.spec.ts"] }