diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..5321e775 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,78 @@ +{ + "editor.defaultFormatter": "vscode.typescript-language-features", + "editor.formatOnSave": true, + "editor.formatOnPaste": false, + "editor.formatOnType": false, + "[typescript]": { + "editor.defaultFormatter": "vscode.typescript-language-features", + "editor.formatOnSave": true + }, + "[typescriptreact]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[javascript]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[json]": { + "editor.defaultFormatter": "vscode.json-language-features", + "editor.formatOnSave": true + }, + "[jsonc]": { + "editor.defaultFormatter": "vscode.json-language-features", + "editor.formatOnSave": true + }, + "[html]": { + "editor.defaultFormatter": "vscode.html-language-features", + "editor.formatOnSave": true + }, + "[css]": { + "editor.defaultFormatter": "vscode.css-language-features", + "editor.formatOnSave": true + }, + "[scss]": { + "editor.defaultFormatter": "vscode.css-language-features", + "editor.formatOnSave": true + }, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + }, + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.validate.enable": true, + "typescript.updateImportsOnFileMove.enabled": "always", + "typescript.preferences.importModuleSpecifier": "relative", + "typescript.preferences.importModuleSpecifierEnding": "auto", + "typescript.preferences.quoteStyle": "single", + "typescript.suggest.autoImports": true, + "typescript.suggest.completeFunctionCalls": true, + "editor.inlineSuggest.enabled": true, + "editor.parameterHints.enabled": true, + "editor.suggestSelection": "first", + "editor.tabCompletion": "on", + "angular.enable-strict-mode-prompt": false, + "angular.trace.server": "off", + "editor.tabSize": 2, + "editor.insertSpaces": true, + "editor.detectIndentation": false, + "files.eol": "\n", + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "editor.wordWrap": "on", + "editor.minimap.enabled": false, + "editor.renderWhitespace": "selection", + "editor.bracketPairColorization.enabled": true, + "editor.guides.bracketPairs": true, + "files.exclude": { + "**/.angular/**": true, + "**/.cache/**": true, + "**/dist/**": true, + "**/coverage/**": true, + "**/.DS_Store": true + }, + "git.autofetch": true, + "git.confirmSync": false, + "explorer.compactFolders": false, + "workbench.startupEditor": "none" +} diff --git a/cypress/e2e/dashboard.cy.ts b/cypress/e2e/dashboard.cy.ts index 933e66be..192d61b3 100644 --- a/cypress/e2e/dashboard.cy.ts +++ b/cypress/e2e/dashboard.cy.ts @@ -13,18 +13,21 @@ describe('/dashboard',{ it('should have all required elements in dashboard', ()=>{ checkHeaderPreLogin() - cy.getBySel('browseServices').should('not.be.disabled') + cy.getBySel('browseServicesDashboard').should('not.be.disabled') cy.getBySel('mainText').should('exist') cy.getBySel('publishOff').should('exist') cy.getBySel('publishOff').should('have.attr', 'href', init_config.domeRegister) cy.getBySel('vServices').should('exist') - cy.getBySel('vServices').should('have.text', '1 verified services') + cy.getBySel('vServices').invoke('text').then((text) => { + expect(text.trim()).to.eq('1 verified services') + }) cy.getBySel('rPublishers').should('exist') - cy.getBySel('rPublishers').should('have.text', '1 registered providers') + cy.getBySel('rPublishers').invoke('text').then((text) => { + expect(text.trim()).to.eq('1 registered providers') + }) cy.getBySel('nameServices').should('have.length', init_stat.services.length) cy.getBySel('nameOrgs').should('have.length', init_stat.organizations.length) }) }) - diff --git a/cypress/support/constants.ts b/cypress/support/constants.ts index 275e0895..80030f2e 100644 --- a/cypress/support/constants.ts +++ b/cypress/support/constants.ts @@ -237,18 +237,20 @@ export const checkHeaderPreLogin = () => { if ($body.find('[data-cy=publishOffering]').length > 0) cy.getBySel('publishOffering').should('exist') if ($body.find('[data-cy=browse]').length > 0) cy.getBySel('browse').should('exist') if ($body.find('[data-cy=about]').length > 0) cy.getBySel('about').should('exist') + if ($body.find('[data-cy=knowledge]').length > 0) { + cy.getBySel('knowledge').should('exist') + cy.getBySel('knowledge').should('have.attr', 'href', init_config.knowledgeBaseUrl) + } + if ($body.find('[data-cy=darkMode]').length > 0) { + cy.getBySel('darkMode').should('exist') + cy.getBySel('darkMode').click() + cy.getBySel('moonSVG').should('be.hidden') + cy.getBySel('sunSVG').should('not.be.hidden') + cy.getBySel('darkMode').click() + cy.getBySel('sunSVG').should('be.hidden') + cy.getBySel('moonSVG').should('not.be.hidden') + } }) - cy.getBySel('knowledge').should('exist') - cy.getBySel('darkMode').should('exist') - - cy.getBySel('darkMode').click() - cy.getBySel('moonSVG').should('be.hidden') - cy.getBySel('sunSVG').should('not.be.hidden') - cy.getBySel('darkMode').click() - cy.getBySel('sunSVG').should('be.hidden') - cy.getBySel('moonSVG').should('not.be.hidden') - - cy.getBySel('knowledge').should('have.attr', 'href', init_config.knowledgeBaseUrl) }; export const checkHeaderPostLogin = () => { @@ -259,18 +261,20 @@ export const checkHeaderPostLogin = () => { if ($body.find('[data-cy=publishOffering]').length > 0) cy.getBySel('publishOffering').should('exist') if ($body.find('[data-cy=browse]').length > 0) cy.getBySel('browse').should('exist') if ($body.find('[data-cy=about]').length > 0) cy.getBySel('about').should('exist') + if ($body.find('[data-cy=knowledge]').length > 0) { + cy.getBySel('knowledge').should('exist') + cy.getBySel('knowledge').should('have.attr', 'href', init_config.knowledgeBaseUrl) + } + if ($body.find('[data-cy=darkMode]').length > 0) { + cy.getBySel('darkMode').should('exist') + cy.getBySel('darkMode').click() + cy.getBySel('moonSVG').should('be.hidden') + cy.getBySel('sunSVG').should('not.be.hidden') + cy.getBySel('darkMode').click() + cy.getBySel('sunSVG').should('be.hidden') + cy.getBySel('moonSVG').should('not.be.hidden') + } }) - cy.getBySel('knowledge').should('exist') - cy.getBySel('darkMode').should('exist') - - cy.getBySel('darkMode').click() - cy.getBySel('moonSVG').should('be.hidden') - cy.getBySel('sunSVG').should('not.be.hidden') - cy.getBySel('darkMode').click() - cy.getBySel('sunSVG').should('be.hidden') - cy.getBySel('moonSVG').should('not.be.hidden') - - cy.getBySel('knowledge').should('have.attr', 'href', init_config.knowledgeBaseUrl) }; diff --git a/src/app/app.component.css b/src/app/app.component.css index e69de29b..75243035 100644 --- a/src/app/app.component.css +++ b/src/app/app.component.css @@ -0,0 +1,10 @@ +.app-content { + min-height: calc(100vh - 88px); + min-height: calc(100dvh - 88px); + display: flex; + flex-direction: column; +} + +.app-content > main { + flex: 1 0 auto; +} diff --git a/src/app/app.component.html b/src/app/app.component.html index 16a1a252..0ad9b233 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,17 +1,22 @@ - + -
- -
-@if (providerThemeName == "DOME") { - -} +
+
+ +
+ + +
- +@if (providerThemeName === "DOME") { + +} @if(isProduction){ - -} \ No newline at end of file + + + +} diff --git a/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.css b/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.css new file mode 100644 index 00000000..e82a9da3 --- /dev/null +++ b/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.css @@ -0,0 +1,215 @@ +.dc-wrap { + position: relative; + width: 100%; + isolation: isolate; +} + +.dc-bg { + position: absolute; + inset: 0; + z-index: 0; + overflow: hidden; + pointer-events: none; + background: #f3f6ff; +} + +.dc-content { + position: relative; + z-index: 1; +} + +.dc-ellipse { + position: absolute; + width: 720px; + height: 720px; + border-radius: 9999px; + transform: rotate(180deg); + opacity: 1; + background: radial-gradient(circle at 35% 35%, + rgba(182, 202, 236, 0.95) 0%, + rgba(182, 202, 236, 0.65) 38%, + rgba(182, 202, 236, 0) 72%); + filter: blur(10px); +} + +.dc-e1 { + left: -220px; + top: -190px; +} + +.dc-e2 { + right: -260px; + top: 60px; +} + +.dc-e3 { + left: 50%; + top: -240px; + transform: translateX(-50%) rotate(180deg); +} + +.dc-e4 { + left: 140px; + bottom: -360px; +} + +.dc-blur { + position: absolute; + inset: 0; + background: linear-gradient(226.59deg, + rgba(255, 242, 242, 0.18) 25.7%, + rgba(255, 250, 250, 0.28) 94.73%); + backdrop-filter: blur(90px); + -webkit-backdrop-filter: blur(90px); + transform: rotate(180deg); +} + +.dc-feature-card { + position: relative; + min-height: 180px; + border-radius: 12px; + overflow: hidden; + background: rgba(255, 255, 255, 0.95); + box-shadow: 0 10px 30px rgba(13, 33, 74, 0.1); + border: 1px solid rgba(0, 0, 0, 0.05); + transition: transform 220ms ease, box-shadow 220ms ease; +} + +.dc-feature-card:hover { + transform: translateY(-2px); + box-shadow: 0 16px 38px rgba(13, 33, 74, 0.14); +} + +.dc-feature-card__base { + position: relative; + z-index: 1; + height: 100%; + min-height: 180px; + transition: opacity 180ms ease, transform 220ms ease; +} + +.dc-feature-card__content { + height: 100%; + display: flex; + align-items: flex-end; + padding: 1.5rem; +} + +.dc-feature-card__icon { + position: absolute; + right: 0; + bottom: 0; + font-size: 72px; + color: #1f4fbf; + opacity: 0.1; + transition: opacity 220ms ease, transform 220ms ease; +} + +.dc-feature-card__hover { + position: absolute; + inset: 0; + z-index: 2; + padding: 2rem 1.9rem 1.8rem; + background: rgba(226, 233, 245, 0.9); + opacity: 0; + transform: translateY(8px); + transition: opacity 220ms ease, transform 220ms ease; + pointer-events: none; +} + +.dc-feature-card__hover-text { + position: relative; + z-index: 2; + max-width: 250px; + font-size: 16px; + line-height: 1.55; + font-weight: 500; + color: #1f2937; +} + +.dc-feature-card__hover-icon { + position: absolute; + right: -6px; + bottom: -10px; + font-size: 122px; + color: #1f4fbf; + opacity: 0.1; + z-index: 1; + transition: transform 220ms ease, opacity 220ms ease; +} + +.dc-feature-card:hover .dc-feature-card__base { + opacity: 0; + transform: scale(0.98); +} + +.dc-feature-card:hover .dc-feature-card__icon { + opacity: 0; + transform: scale(0.9); +} + +.dc-feature-card:hover .dc-feature-card__hover { + opacity: 1; + transform: translateY(0); +} + +.dc-feature-card:hover .dc-feature-card__hover-icon { + opacity: 0.12; + transform: scale(1.03); +} + +@media (max-width: 1024px) { + .dc-ellipse { + width: 620px; + height: 620px; + filter: blur(9px); + } + + .dc-e2 { + right: -300px; + } +} + +@media (max-width: 640px) { + .dc-ellipse { + width: 520px; + height: 520px; + filter: blur(8px); + } + + .dc-e1 { + left: -280px; + top: -230px; + } + + .dc-e2 { + right: -320px; + top: 10px; + } + + .dc-e4 { + left: 40px; + bottom: -380px; + } + + .dc-feature-card { + min-height: 160px; + } + + .dc-feature-card__base { + min-height: 160px; + } + + .dc-feature-card__hover { + padding: 1.5rem; + } + + .dc-feature-card__hover-text { + font-size: 16px; + line-height: 1.65; + } + + .dc-feature-card__hover-icon { + font-size: 104px; + } +} diff --git a/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.html b/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.html new file mode 100644 index 00000000..c0b172a7 --- /dev/null +++ b/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.html @@ -0,0 +1,80 @@ +
+ + +
+

+ {{ 'DASHBOARD.customers._sectitle' | translate }} +

+ +
+
+ @if (featureCards.length) { +
+ @for (card of featureCards; track $index) { +
+
+
+
+
+
+ + +
+ +
+
+ {{ card.hoverText | translate }} +
+ + +
+
+ } +
+ } +
+ +
+
+

+ {{ 'DASHBOARD.customers._howItWorksTitle' | translate }} +

+ + @if (steps.length) { +
+ @for (step of steps; track $index) { +
+
{{ step.num }}
+ +
+
+ {{ step.title | translate }} +
+
+ {{ step.desc | translate }} +
+
+
+ } +
+ } + + +
+
+
+
+
diff --git a/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.ts b/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.ts new file mode 100644 index 00000000..274057d2 --- /dev/null +++ b/src/app/pages/dashboard/dashboard-customers/dashboard-customers.component.ts @@ -0,0 +1,61 @@ +import { Component, input } from "@angular/core"; +import { RouterLink } from '@angular/router'; +import { FontAwesomeModule } from "@fortawesome/angular-fontawesome"; +import { faCircleCheck, faEye } from "@fortawesome/free-regular-svg-icons"; +import { faBoltLightning, faDiagramProject } from "@fortawesome/free-solid-svg-icons"; +import { TranslateModule } from '@ngx-translate/core'; + +type FeatureCard = { html: string; hoverText: string; icon: any }; +type Step = { num: string; title: string; desc: string }; + +@Component({ + selector: "app-dashboard-customers", + standalone: true, + imports: [FontAwesomeModule, TranslateModule, RouterLink], + templateUrl: "./dashboard-customers.component.html", + styleUrl: "./dashboard-customers.component.css" +}) +export class DashboardCustomersComponent { + customerLink = input.required(); + + featureCards: FeatureCard[] = [ + { + html: 'DASHBOARD.customers._cards.access.title', + hoverText: 'DASHBOARD.customers._cards.access.desc', + icon: faCircleCheck + }, + { + html: 'DASHBOARD.customers._cards.discovery.title', + hoverText: 'DASHBOARD.customers._cards.discovery.desc', + icon: faEye + }, + { + html: 'DASHBOARD.customers._cards.procurement.title', + hoverText: 'DASHBOARD.customers._cards.procurement.desc', + icon: faBoltLightning + }, + { + html: 'DASHBOARD.customers._cards.ecosystem.title', + hoverText: 'DASHBOARD.customers._cards.ecosystem.desc', + icon: faDiagramProject + } + ]; + + steps: Step[] = [ + { + num: '01', + title: 'DASHBOARD.customers._steps.register.title', + desc: 'DASHBOARD.customers._steps.register.desc' + }, + { + num: '02', + title: 'DASHBOARD.customers._steps.search.title', + desc: 'DASHBOARD.customers._steps.search.desc' + }, + { + num: '03', + title: 'DASHBOARD.customers._steps.connect.title', + desc: 'DASHBOARD.customers._steps.connect.desc' + } + ]; +} diff --git a/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.css b/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.css new file mode 100644 index 00000000..1eb4facf --- /dev/null +++ b/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.css @@ -0,0 +1,101 @@ +.hero-shell { + background: #070f24; + font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans"; +} + +.hero-bg { + background: + radial-gradient(900px 520px at 50% 44%, rgba(20, 140, 255, 0.14), rgba(7, 15, 36, 0) 62%), + radial-gradient(1200px 700px at 50% 40%, rgba(0, 210, 255, 0.10), rgba(7, 15, 36, 0) 68%), + linear-gradient(180deg, #070f24 0%, #07102a 40%, #060d22 100%); +} + +.hero-title { + font-weight: 800; + letter-spacing: -0.02em; + line-height: 1.05; + font-size: clamp(40px, 4.2vw, 64px); +} + +.hero-accent { + color: #23b9d8; +} + +.hero-sub { + color: rgba(255, 255, 255, 0.55); + font-size: 16px; + line-height: 1.7; +} + +.hero-btn { + height: 52px; + padding: 0 22px; + border-radius: 10px; + font-weight: 700; + font-size: 14px; + letter-spacing: 0.01em; + transition: transform 160ms ease, box-shadow 160ms ease, background-color 160ms ease, border-color 160ms ease; + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 260px; +} + +.hero-btn:active { + transform: translateY(1px); +} + +.hero-btn--primary { + background: #2D58A7; + color: #fff; + box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28); +} + +.hero-btn--primary:hover { + background: #00ADD3; + box-shadow: 0 22px 55px rgba(0, 0, 0, 0.32); +} + +.hero-btn--ghost { + background: transparent; + border: 1px solid rgba(90, 140, 255, 0.45); + color: rgba(255, 255, 255, 0.92); + box-shadow: 0 12px 34px rgba(0, 0, 0, 0.20); + backdrop-filter: blur(6px); +} + +.hero-btn--ghost:hover { + border-color: #2D58A7; + color: #2D58A7; + background: white; +} + +.logo-ph { + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 999px; + border: 1px solid rgba(255, 255, 255, 0.14); + color: rgba(255, 255, 255, 0.60); + font-weight: 700; + letter-spacing: 0.12em; + font-size: 12px; +} + +.earth-wrapper { + position: absolute; + bottom: -2%; + left: 50%; + transform: translateX(-50%); + width: min(1600px, 140vw); + pointer-events: none; + opacity: 0.95; +} + +.earth-wrapper img { + width: 100%; + height: auto; + display: block; + filter: drop-shadow(0 0 40px rgba(120, 220, 255, 0.35)); +} diff --git a/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.html b/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.html new file mode 100644 index 00000000..547df90a --- /dev/null +++ b/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.html @@ -0,0 +1,94 @@ +
+
+

+ {{ 'DASHBOARD.ecosystem._title' | translate }} +

+ +

+ {{ 'DASHBOARD.ecosystem._subtitle' | translate }} +

+ +
+
+
+ {{ 'DASHBOARD.ecosystem._nowLabel' | translate }} +
+
+ {{ 'DASHBOARD.ecosystem._nextLabel' | translate }} +
+
+ {{ 'DASHBOARD.ecosystem._beyondLabel' | translate }} +
+
+ +
+
+ +
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ + @if (milestones.length) { +
+ @for (milestone of milestones; track $index) { +
+
+ {{ milestone.title | translate }} +
+ +
+ {{ milestone.desc | translate }} +
+
+ } +
+ } +
+ + +
+
diff --git a/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.ts b/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.ts new file mode 100644 index 00000000..694ab41a --- /dev/null +++ b/src/app/pages/dashboard/dashboard-ecosystem/dashboard-ecosystem.component.ts @@ -0,0 +1,38 @@ +import { Component, input } from "@angular/core"; +import { TranslateModule } from '@ngx-translate/core'; + +type Milestone = { + title: string; + desc: string; + active: boolean; +}; + +@Component({ + selector: "app-dashboard-ecosystem", + standalone: true, + templateUrl: "./dashboard-ecosystem.component.html", + imports: [TranslateModule] +}) +export class DashboardEcosystemComponent { + + providersLink = input.required(); + customersLink = input.required(); + + milestones: Milestone[] = [ + { + title: "DASHBOARD.ecosystem._milestones._live._title", + desc: "DASHBOARD.ecosystem._milestones._live._desc", + active: true, + }, + { + title: "DASHBOARD.ecosystem._milestones._tools._title", + desc: "DASHBOARD.ecosystem._milestones._tools._desc", + active: false, + }, + { + title: "DASHBOARD.ecosystem._milestones._federation._title", + desc: "DASHBOARD.ecosystem._milestones._federation._desc", + active: false, + }, + ]; +} diff --git a/src/app/pages/dashboard/dashboard-footer/dashboard-footer.component.html b/src/app/pages/dashboard/dashboard-footer/dashboard-footer.component.html index 3bc12bfa..c4d0afa3 100644 --- a/src/app/pages/dashboard/dashboard-footer/dashboard-footer.component.html +++ b/src/app/pages/dashboard/dashboard-footer/dashboard-footer.component.html @@ -1,59 +1,52 @@ -