diff --git a/.vscode/settings.json b/.vscode/settings.json index 9bf4d12b5..ba68f1b50 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true + "editor.formatOnSave": true, + "vsicons.presets.angular": true } diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts b/apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts new file mode 100644 index 000000000..fee6f0064 --- /dev/null +++ b/apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { ResourcesGlossaryPageComponent } from './resources-glossary.component'; + +const routes: Routes = [ + { + path: '', + component: ResourcesGlossaryPageComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ResourcesGlossaryRoutingModule {} diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary.component.html b/apps/client/src/app/pages/resources/glossary/resources-glossary.component.html new file mode 100644 index 000000000..7225a4e69 --- /dev/null +++ b/apps/client/src/app/pages/resources/glossary/resources-glossary.component.html @@ -0,0 +1,16 @@ +
+
+
+

Glossary

+
+ @for (item of glossaryItems; track item) { +
+

{{ item.term }}

+

{{ item.definition }}

+ Learn more → +
+ } +
+
+
+
diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary.component.scss b/apps/client/src/app/pages/resources/glossary/resources-glossary.component.scss new file mode 100644 index 000000000..e2d265315 --- /dev/null +++ b/apps/client/src/app/pages/resources/glossary/resources-glossary.component.scss @@ -0,0 +1,47 @@ +:host { + display: block; + padding: 1rem; +} + +// Target the parent panel +:host-context(.mat-tab-nav-panel) { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + + &::-webkit-scrollbar { + /* Chrome, Safari and Opera */ + display: none; + } +} + +.container { + max-width: 800px; + margin: 0 auto; +} + +h1 { + margin-bottom: 2rem; +} + +.glossary-list { + .mb-4 { + margin-bottom: 2rem; + } + + h3 { + margin-bottom: 0.5rem; + } + + p { + margin-bottom: 0.5rem; + } + + a { + color: #007bff; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } +} diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts b/apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts new file mode 100644 index 000000000..4360c3b23 --- /dev/null +++ b/apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts @@ -0,0 +1,53 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'gf-resources-glossary', + templateUrl: './resources-glossary.component.html', + styleUrls: ['./resources-glossary.component.scss'] +}) +export class ResourcesGlossaryPageComponent { + public glossaryItems = [ + { + term: 'Buy and Hold', + definition: + 'Buy and hold is a passive investment strategy where you buy assets and hold them for a long period regardless of fluctuations in the market.', + link: 'https://www.investopedia.com/terms/b/buyandhold.asp' + }, + { + term: 'Deflation', + definition: + 'Deflation is a decrease of the general price level for goods and services in an economy over a period of time.', + link: 'https://www.investopedia.com/terms/d/deflation.asp' + }, + { + term: 'Dollar-Cost Averaging (DCA)', + definition: + 'Dollar-cost averaging is an investment strategy where you split the total amount to be invested across periodic purchases of a target asset to reduce the impact of volatility on the overall purchase.', + link: 'https://www.investopedia.com/terms/d/dollarcostaveraging.asp' + }, + { + term: 'Financial Independence', + definition: + 'Financial independence is the status of having enough income, for example with a passive income like dividends, to cover your living expenses for the rest of your life.', + link: 'https://en.wikipedia.org/wiki/Financial_independence' + }, + { + term: 'FIRE', + definition: + 'FIRE is a movement that promotes saving and investing to achieve financial independence and early retirement.', + link: '../en/blog/2023/07/exploring-the-path-to-fire' + }, + { + term: 'Inflation', + definition: + 'Inflation is an increase of the general price level for goods and services in an economy over a period of time.', + link: 'https://www.investopedia.com/terms/i/inflation.asp' + }, + { + term: 'Stagflation', + definition: + 'Stagflation describes a situation in which there is a stagnant economy with high unemployment and high inflation.', + link: 'https://www.investopedia.com/terms/s/stagflation.asp' + } + ]; +} diff --git a/apps/client/src/app/pages/resources/glossary/resources-glossary.module.ts b/apps/client/src/app/pages/resources/glossary/resources-glossary.module.ts new file mode 100644 index 000000000..1c19fbc5f --- /dev/null +++ b/apps/client/src/app/pages/resources/glossary/resources-glossary.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { ResourcesGlossaryRoutingModule } from './resources-glossary-routing.module'; +import { ResourcesGlossaryPageComponent } from './resources-glossary.component'; + +@NgModule({ + declarations: [ResourcesGlossaryPageComponent], + imports: [CommonModule, ResourcesGlossaryRoutingModule] +}) +export class ResourcesGlossaryPageModule {} diff --git a/apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts b/apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts new file mode 100644 index 000000000..da53f2956 --- /dev/null +++ b/apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { ResourcesGuidesComponent } from './resources-guides.component'; + +const routes: Routes = [ + { + path: '', + component: ResourcesGuidesComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ResourcesGuidesRoutingModule {} diff --git a/apps/client/src/app/pages/resources/guides/resources-guides.component.html b/apps/client/src/app/pages/resources/guides/resources-guides.component.html new file mode 100644 index 000000000..d130ae668 --- /dev/null +++ b/apps/client/src/app/pages/resources/guides/resources-guides.component.html @@ -0,0 +1,16 @@ +
+
+
+

Guides

+
+ @for (guide of guides; track guide) { +
+

{{ guide.title }}

+

{{ guide.description }}

+ Read more → +
+ } +
+
+
+
diff --git a/apps/client/src/app/pages/resources/guides/resources-guides.component.scss b/apps/client/src/app/pages/resources/guides/resources-guides.component.scss new file mode 100644 index 000000000..4e9a621c1 --- /dev/null +++ b/apps/client/src/app/pages/resources/guides/resources-guides.component.scss @@ -0,0 +1,43 @@ +:host { + display: block; + color: rgb(var(--dark-primary-text)); + + .container { + max-width: 800px; + margin: 0 auto; + } + + h1 { + margin-bottom: 2rem; + } + + .guides-list { + .mb-4 { + margin-bottom: 2rem; + } + + h3 { + margin-top: 0; + margin-bottom: 0.5rem; + } + + p { + margin-bottom: 0.5rem; + } + + a { + color: rgba(var(--palette-primary-500), 1); + font-weight: 500; + text-decoration: none; + + &:hover { + color: rgba(var(--palette-primary-300), 1); + text-decoration: underline; + } + } + } +} + +:host-context(.theme-dark) { + color: rgb(var(--light-primary-text)); +} diff --git a/apps/client/src/app/pages/resources/guides/resources-guides.component.ts b/apps/client/src/app/pages/resources/guides/resources-guides.component.ts new file mode 100644 index 000000000..06852b2fb --- /dev/null +++ b/apps/client/src/app/pages/resources/guides/resources-guides.component.ts @@ -0,0 +1,23 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'gf-resources-guides', + templateUrl: './resources-guides.component.html', + styleUrls: ['./resources-guides.component.scss'] +}) +export class ResourcesGuidesComponent { + public guides = [ + { + title: 'Boringly Getting Rich', + description: + 'The Boringly Getting Rich guide supports you to get started with investing. It introduces a strategy utilizing a broadly diversified, low-cost portfolio excluding the risks of individual stocks.', + link: 'https://herget.me/investing-guide' + }, + { + title: 'How do I get my finances in order?', + description: + 'Before you can think of long-term investing, you have to get your finances in order. Learn how you can reach your financial goals easier and faster in this guide.', + link: '../en/blog/2022/07/how-do-i-get-my-finances-in-order' + } + ]; +} diff --git a/apps/client/src/app/pages/resources/guides/resources-guides.module.ts b/apps/client/src/app/pages/resources/guides/resources-guides.module.ts new file mode 100644 index 000000000..fcfcb3625 --- /dev/null +++ b/apps/client/src/app/pages/resources/guides/resources-guides.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { ResourcesGuidesRoutingModule } from './resources-guides-routing.module'; +import { ResourcesGuidesComponent } from './resources-guides.component'; + +@NgModule({ + declarations: [ResourcesGuidesComponent], + imports: [CommonModule, ResourcesGuidesRoutingModule] +}) +export class ResourcesGuidesModule {} diff --git a/apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts b/apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts new file mode 100644 index 000000000..5dd9d0ff8 --- /dev/null +++ b/apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { ResourcesMarketsComponent } from './resources-markets.component'; + +const routes: Routes = [ + { + path: '', + component: ResourcesMarketsComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ResourcesMarketsRoutingModule {} diff --git a/apps/client/src/app/pages/resources/markets/resources-markets.component.html b/apps/client/src/app/pages/resources/markets/resources-markets.component.html new file mode 100644 index 000000000..e6aae43c2 --- /dev/null +++ b/apps/client/src/app/pages/resources/markets/resources-markets.component.html @@ -0,0 +1,16 @@ +
+
+
+

Markets

+
+ @for (resource of marketResources; track resource) { +
+

{{ resource.title }}

+

{{ resource.description }}

+ View resource → +
+ } +
+
+
+
diff --git a/apps/client/src/app/pages/resources/markets/resources-markets.component.scss b/apps/client/src/app/pages/resources/markets/resources-markets.component.scss new file mode 100644 index 000000000..f02ff31be --- /dev/null +++ b/apps/client/src/app/pages/resources/markets/resources-markets.component.scss @@ -0,0 +1,54 @@ +:host { + color: rgb(var(--dark-primary-text)); + display: block; + + .market-resources { + display: grid; + gap: 1rem; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + + .mat-mdc-card { + height: 100%; + transition: border-color 0.3s ease; + + &:hover { + border-color: var(--gf-theme-primary-500); + } + + .mat-mdc-card-header { + .mat-mdc-card-title { + font-size: 1.1rem; + } + } + + .mat-mdc-card-content { + font-size: 0.9rem; + } + + .mat-mdc-card-actions { + padding: 0 1rem 1rem; + } + + a { + color: rgba(var(--palette-primary-500), 1); + font-weight: 500; + text-decoration: none; + + &:hover { + color: rgba(var(--palette-primary-300), 1); + text-decoration: underline; + } + } + } + } +} + +:host-context(.theme-dark) { + color: rgb(var(--light-primary-text)); + + .market-resources { + .mat-mdc-card { + background-color: rgba(var(--palette-background-card-dark), 1); + } + } +} diff --git a/apps/client/src/app/pages/resources/markets/resources-markets.component.ts b/apps/client/src/app/pages/resources/markets/resources-markets.component.ts new file mode 100644 index 000000000..32585d496 --- /dev/null +++ b/apps/client/src/app/pages/resources/markets/resources-markets.component.ts @@ -0,0 +1,35 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'gf-resources-markets', + templateUrl: './resources-markets.component.html', + styleUrls: ['./resources-markets.component.scss'] +}) +export class ResourcesMarketsComponent { + public marketResources = [ + { + title: 'Crypto Coins Heatmap', + description: + 'With the Crypto Coins Heatmap you can track the daily market movements of cryptocurrencies as a visual snapshot.', + link: 'https://www.tradingview.com/heatmap/crypto' + }, + { + title: 'Fear & Greed Index', + description: + 'The fear and greed index was developed by CNNMoney to measure the primary emotions (fear and greed) that influence how much investors are willing to pay for stocks.', + link: 'https://money.cnn.com/data/fear-and-greed/' + }, + { + title: 'Inflation Chart', + description: + 'Inflation Chart helps you find the intrinsic value of stock markets, stock prices, goods and services by adjusting them to the amount of the money supply (M0, M1, M2) or price of other goods (food or oil).', + link: 'https://inflationchart.com' + }, + { + title: 'Stock Heatmap', + description: + 'With the Stock Heatmap you can track the daily market movements of stocks as a visual snapshot.', + link: 'https://www.tradingview.com/heatmap/stock' + } + ]; +} diff --git a/apps/client/src/app/pages/resources/markets/resources-markets.module.ts b/apps/client/src/app/pages/resources/markets/resources-markets.module.ts new file mode 100644 index 000000000..3ec93bb3b --- /dev/null +++ b/apps/client/src/app/pages/resources/markets/resources-markets.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { ResourcesMarketsRoutingModule } from './resources-markets-routing.module'; +import { ResourcesMarketsComponent } from './resources-markets.component'; + +@NgModule({ + declarations: [ResourcesMarketsComponent], + imports: [CommonModule, ResourcesMarketsRoutingModule] +}) +export class ResourcesMarketsModule {} diff --git a/apps/client/src/app/pages/resources/overview/resources-overview-routing.module.ts b/apps/client/src/app/pages/resources/overview/resources-overview-routing.module.ts new file mode 100644 index 000000000..e546c5412 --- /dev/null +++ b/apps/client/src/app/pages/resources/overview/resources-overview-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { ResourcesOverviewComponent } from './resources-overview.component'; + +const routes: Routes = [ + { + path: '', + component: ResourcesOverviewComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ResourcesOverviewRoutingModule {} diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.component.html b/apps/client/src/app/pages/resources/overview/resources-overview.component.html new file mode 100644 index 000000000..3a3cfb915 --- /dev/null +++ b/apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -0,0 +1,16 @@ +
+
+
+

Resources Overview

+
+ @for (item of overviewItems; track item) { +
+

{{ item.title }}

+

{{ item.description }}

+ Explore → +
+ } +
+
+
+
diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.component.scss b/apps/client/src/app/pages/resources/overview/resources-overview.component.scss new file mode 100644 index 000000000..8ff4cc7a0 --- /dev/null +++ b/apps/client/src/app/pages/resources/overview/resources-overview.component.scss @@ -0,0 +1,43 @@ +:host { + display: block; + color: rgb(var(--dark-primary-text)); +} + +.container { + max-width: 800px; + margin: 0 auto; +} + +h1 { + margin-bottom: 2rem; +} + +.overview-list { + .mb-4 { + margin-bottom: 2rem; + } + + h3 { + margin-top: 0; + margin-bottom: 0.5rem; + } + + p { + margin-bottom: 0.5rem; + } + + a { + color: rgba(var(--palette-primary-500), 1); + font-weight: 500; + text-decoration: none; + + &:hover { + color: rgba(var(--palette-primary-300), 1); + text-decoration: underline; + } + } +} + +:host-context(.theme-dark) { + color: rgb(var(--light-primary-text)); +} diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.component.ts b/apps/client/src/app/pages/resources/overview/resources-overview.component.ts new file mode 100644 index 000000000..f790d2fe9 --- /dev/null +++ b/apps/client/src/app/pages/resources/overview/resources-overview.component.ts @@ -0,0 +1,35 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'gf-resources-overview', + templateUrl: './resources-overview.component.html', + styleUrls: ['./resources-overview.component.scss'] +}) +export class ResourcesOverviewComponent { + public overviewItems = [ + { + title: 'Frequently Asked Questions (FAQ)', + description: + 'Find quick answers to commonly asked questions about Ghostfolio in our Frequently Asked Questions (FAQ) section.', + link: '/faq' + }, + { + title: 'Guides', + description: + 'Explore our guides to help you get started with investing and managing your finances.', + link: '/resources/guides' + }, + { + title: 'Markets', + description: + 'Access various market resources and tools to stay informed about financial markets.', + link: '/resources/markets' + }, + { + title: 'Glossary', + description: + 'Learn key financial terms and concepts in our comprehensive glossary.', + link: '/resources/glossary' + } + ]; +} diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.module.ts b/apps/client/src/app/pages/resources/overview/resources-overview.module.ts new file mode 100644 index 000000000..6cac8ced4 --- /dev/null +++ b/apps/client/src/app/pages/resources/overview/resources-overview.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { ResourcesOverviewRoutingModule } from './resources-overview-routing.module'; +import { ResourcesOverviewComponent } from './resources-overview.component'; + +@NgModule({ + declarations: [ResourcesOverviewComponent], + imports: [CommonModule, RouterModule, ResourcesOverviewRoutingModule] +}) +export class ResourcesOverviewModule {} diff --git a/apps/client/src/app/pages/resources/resources-page-routing.module.ts b/apps/client/src/app/pages/resources/resources-page-routing.module.ts index be2eaa24e..e8edfeaa1 100644 --- a/apps/client/src/app/pages/resources/resources-page-routing.module.ts +++ b/apps/client/src/app/pages/resources/resources-page-routing.module.ts @@ -3,22 +3,48 @@ import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; +// import { ResourcesGlossaryPageComponent } from './glossary/resources-glossary.component'; +// import { ResourcesGuidesComponent } from './guides/resources-guides.component'; +// import { ResourcesMarketsComponent } from './markets/resources-markets.component'; +// import { ResourcesOverviewComponent } from './overview/resources-overview.component'; import { ResourcesPageComponent } from './resources-page.component'; const routes: Routes = [ { - canActivate: [AuthGuard], - component: ResourcesPageComponent, path: '', - title: $localize`Resources` - }, - ...['personal-finance-tools'].map((path) => ({ - path, - loadChildren: () => - import( - './personal-finance-tools/personal-finance-tools-page.module' - ).then((m) => m.PersonalFinanceToolsPageModule) - })) + component: ResourcesPageComponent, + canActivate: [AuthGuard], + children: [ + { + path: 'guides', + loadChildren: () => + import('./guides/resources-guides.module').then( + (m) => m.ResourcesGuidesModule + ) + }, + { + path: 'markets', + loadChildren: () => + import('./markets/resources-markets.module').then( + (m) => m.ResourcesMarketsModule + ) + }, + { + path: 'glossary', + loadChildren: () => + import('./glossary/resources-glossary.module').then( + (m) => m.ResourcesGlossaryPageModule + ) + }, + { + path: '', + loadChildren: () => + import('./overview/resources-overview.module').then( + (m) => m.ResourcesOverviewModule + ) + } + ] + } ]; @NgModule({ diff --git a/apps/client/src/app/pages/resources/resources-page.component.ts b/apps/client/src/app/pages/resources/resources-page.component.ts index 51172c0de..298064632 100644 --- a/apps/client/src/app/pages/resources/resources-page.component.ts +++ b/apps/client/src/app/pages/resources/resources-page.component.ts @@ -6,10 +6,10 @@ import { Component, OnInit } from '@angular/core'; import { Subject } from 'rxjs'; @Component({ - host: { class: 'page' }, + host: { class: 'page has-tabs' }, selector: 'gf-resources-page', - styleUrls: ['./resources-page.scss'], - templateUrl: './resources-page.html' + templateUrl: './resources-page.html', + styleUrls: ['./resources-page.scss'] }) export class ResourcesPageComponent implements OnInit { public hasPermissionForSubscription: boolean; @@ -19,6 +19,20 @@ export class ResourcesPageComponent implements OnInit { '/' + $localize`:snake-case:resources`, 'personal-finance-tools' ]; + public tabs = [ + { + path: '.', + label: $localize`Overview`, + iconName: 'information-circle-outline' + }, + { path: 'guides', label: $localize`Guides`, iconName: 'book-outline' }, + { + path: 'markets', + label: $localize`Markets`, + iconName: 'trending-up-outline' + }, + { path: 'glossary', label: $localize`Glossary`, iconName: 'list-outline' } + ]; private unsubscribeSubject = new Subject(); diff --git a/apps/client/src/app/pages/resources/resources-page.html b/apps/client/src/app/pages/resources/resources-page.html index 49c3d1523..a9dbee450 100644 --- a/apps/client/src/app/pages/resources/resources-page.html +++ b/apps/client/src/app/pages/resources/resources-page.html @@ -1,258 +1,30 @@ -
-
-
-

Resources

-

Ghostfolio

-
-
-
-

Frequently Asked Questions (FAQ)

-
- Find quick answers to commonly asked questions about Ghostfolio in - our Frequently Asked Questions (FAQ) section. -
- -
-
-
-

Guides

-
-
-
-

Boringly Getting Rich

-
- The Boringly Getting Rich guide supports you to get started - with investing. It introduces a strategy utilizing a broadly - diversified, low-cost portfolio excluding the risks of individual - stocks. -
- -
-
-
-
-

How do I get my finances in order?

-
- Before you can think of long-term investing, you have to get your - finances in order. Learn how you can reach your financial goals - easier and faster in this guide. -
- -
-
-
-

Markets

-
-
-
-

Crypto Coins Heatmap

-
- With the Crypto Coins Heatmap you can track the daily - market movements of cryptocurrencies as a visual snapshot. -
- -
-
-
-
-

Fear & Greed Index

-
- The fear and greed index was developed by CNNMoney to - measure the primary emotions (fear and greed) that influence how - much investors are willing to pay for stocks. -
- -
-
-
-
-

Inflation Chart

-
- Inflation Chart helps you find the intrinsic value of stock - markets, stock prices, goods and services by adjusting them to the - amount of the money supply (M0, M1, M2) or price of other goods - (food or oil). -
- -
-
-
-
-

Stock Heatmap

-
- With the Stock Heatmap you can track the daily market - movements of stocks as a visual snapshot. -
- -
-
-
-

Glossary

-
-
-
-

Buy and Hold

-
- Buy and hold is a passive investment strategy where you buy assets - and hold them for a long period regardless of fluctuations in the - market. -
- -
-
-
-
-

Deflation

-
- Deflation is a decrease of the general price level for goods and - services in an economy over a period of time. -
- -
-
-
-
-

Dollar-Cost Averaging (DCA)

-
- Dollar-cost averaging is an investment strategy where you split - the total amount to be invested across periodic purchases of a - target asset to reduce the impact of volatility on the overall - purchase. -
- -
-
-
-
-

Financial Independence

-
- Financial independence is the status of having enough income, for - example with a passive income like dividends, to cover your living - expenses for the rest of your life. -
- -
-
-
-
-

FIRE

-
- FIRE is a movement that promotes saving and investing to achieve - financial independence and early retirement. -
-
- FIRE → -
-
-
-
-
-

Inflation

-
- Inflation is an increase of the general price level for goods and - services in an economy over a period of time. -
- -
-
- @if (hasPermissionForSubscription) { -
-
-

Personal Finance Tools

-
- Personal finance tools are software applications that help - individuals manage their money, track expenses, set budgets, - monitor investments, and make informed financial decisions. -
- -
-
- } -
-
-

Stagflation

-
- Stagflation describes a situation in which there is a stagnant - economy with high unemployment and high inflation. -
- -
-
-
-
-
-
+ + + + + diff --git a/apps/client/src/app/pages/resources/resources-page.module.ts b/apps/client/src/app/pages/resources/resources-page.module.ts index 10845a517..c324d1bca 100644 --- a/apps/client/src/app/pages/resources/resources-page.module.ts +++ b/apps/client/src/app/pages/resources/resources-page.module.ts @@ -1,12 +1,19 @@ import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { MatTabsModule } from '@angular/material/tabs'; +import { RouterModule } from '@angular/router'; import { ResourcesPageRoutingModule } from './resources-page-routing.module'; import { ResourcesPageComponent } from './resources-page.component'; @NgModule({ declarations: [ResourcesPageComponent], - imports: [CommonModule, ResourcesPageRoutingModule], + imports: [ + CommonModule, + ResourcesPageRoutingModule, + MatTabsModule, + RouterModule + ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class ResourcesPageModule {} diff --git a/apps/client/src/app/pages/resources/resources-page.scss b/apps/client/src/app/pages/resources/resources-page.scss index c3109fdf7..7a197412b 100644 --- a/apps/client/src/app/pages/resources/resources-page.scss +++ b/apps/client/src/app/pages/resources/resources-page.scss @@ -1,6 +1,13 @@ :host { color: rgb(var(--dark-primary-text)); - display: block; + display: flex; + flex-direction: row; + height: 100%; + + // Add this to ensure proper ordering + nav { + order: 1; // This will force the nav to be first + } a { color: rgba(var(--palette-primary-500), 1); @@ -15,3 +22,56 @@ :host-context(.theme-dark) { color: rgb(var(--light-primary-text)); } + +.mat-tab-nav-bar { + border-top: none; + border-right: 1px solid rgba(0, 0, 0, 0.12); + flex-direction: column; + width: 240px; +} + +.mat-tab-link { + flex-direction: row; + justify-content: flex-start; + height: 48px; + padding: 0 16px; + min-width: auto; + + ion-icon { + font-size: 24px; + } + + .d-none { + margin-left: 8px; + } +} + +@media (max-width: 599px) { + :host { + flex-direction: column-reverse; + } + + .mat-tab-nav-bar { + width: 100%; + border-right: none; + border-top: 1px solid rgba(0, 0, 0, 0.12); + } + + .mat-tab-link { + flex-direction: column; + height: auto; + padding: 8px 16px; + + ion-icon { + font-size: 28px; + } + } +} + +.flex-grow-1 { + flex-grow: 1; +} + +.overflow-auto { + overflow: auto; +} diff --git a/package-lock.json b/package-lock.json index 492600202..35eb282d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@dfinity/principal": "0.15.7", "@dinero.js/currencies": "2.0.0-alpha.8", "@internationalized/number": "3.5.2", + "@ionic/angular": "^8.3.2", "@nestjs/bull": "10.0.1", "@nestjs/cache-manager": "2.2.2", "@nestjs/common": "10.1.3", @@ -4261,6 +4262,36 @@ "@swc/helpers": "^0.5.0" } }, + "node_modules/@ionic/angular": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-8.3.2.tgz", + "integrity": "sha512-mbQgWWOzOHdzYEuixJNl2HJ+QUPAakvaG2D/oh7E+gvmA732ppnpHWF8XR35bpIfQJeBby6/mNZN0Bp9RWAkWw==", + "license": "MIT", + "dependencies": { + "@ionic/core": "8.3.2", + "ionicons": "^7.0.0", + "jsonc-parser": "^3.0.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": ">=16.0.0", + "@angular/forms": ">=16.0.0", + "@angular/router": ">=16.0.0", + "rxjs": ">=7.5.0", + "zone.js": ">=0.13.0" + } + }, + "node_modules/@ionic/core": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.3.2.tgz", + "integrity": "sha512-ptiDXnn4131eKpY862lv7c9xxjly7vi4O+WWCES78E+hXHvTEAundcA5F8eQyb0MFIFvCnOxreTZjRJJnHqPYw==", + "license": "MIT", + "dependencies": { + "@stencil/core": "4.20.0", + "ionicons": "^7.2.2", + "tslib": "^2.1.0" + } + }, "node_modules/@ioredis/commands": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", diff --git a/package.json b/package.json index b83ce5c59..0397b6fde 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@dfinity/principal": "0.15.7", "@dinero.js/currencies": "2.0.0-alpha.8", "@internationalized/number": "3.5.2", + "@ionic/angular": "^8.3.2", "@nestjs/bull": "10.0.1", "@nestjs/cache-manager": "2.2.2", "@nestjs/common": "10.1.3",