Skip to content

Commit

Permalink
closes #10
Browse files Browse the repository at this point in the history
  • Loading branch information
seiyria committed Apr 26, 2024
1 parent bb20c46 commit 486de79
Show file tree
Hide file tree
Showing 10 changed files with 235 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
<ion-col [sizeMd]="3" [sizeXs]="12">
<div class="map-title">Support</div>
<hr>
<div class="map-item">
<a routerLink="/faq">FAQ</a>
</div>
<div class="map-item">
<a target="_blank" href="https://github.com/LederCards">Ask a Question</a>
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ const routes: Routes = [
loadChildren: () =>
import('./sets/sets.module').then((m) => m.SetsPageModule),
},
{
path: 'faq',
loadChildren: () => import('./faq/faq.module').then((m) => m.FaqPageModule),
},
{
path: '**',
redirectTo: '',
Expand Down
3 changes: 0 additions & 3 deletions src/app/card/card.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export class CardPage implements OnInit {
this.template = compiledTemplate(cardData);

this.cardData.set(cardData);
this.loadFAQ();
}

search(query: string) {
Expand All @@ -61,6 +60,4 @@ export class CardPage implements OnInit {
searchTag(tag: string) {
this.search(`tag:"${tag}"`);
}

loadFAQ() {}
}
71 changes: 58 additions & 13 deletions src/app/faq.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { effect, inject, Injectable, Injector, signal } from '@angular/core';
import {
effect,
inject,
Injectable,
Injector,
signal,
type WritableSignal,
} from '@angular/core';
import type { ICardFAQ, ICardFAQEntry } from '../../interfaces';
import { LocaleService } from './locale.service';
import { MetaService } from './meta.service';
Expand All @@ -14,22 +21,25 @@ export class FAQService {
private isReady = signal<boolean>(false);
public ready$ = this.isReady.asReadonly();

private allFAQs: Array<{
productId: string;
locale: string;
url: string;
}> = [];
private allFAQs: WritableSignal<
Array<{
productId: string;
locale: string;
url: string;
}>
> = signal([]);

private faqByProductIdAndLocale: Record<string, Record<string, ICardFAQ[]>> =
{};
private faqByProductIdAndLocale: WritableSignal<
Record<string, Record<string, ICardFAQ[]>>
> = signal({});

private faqByProductLocaleCard: Record<
string,
Record<string, Record<string, ICardFAQEntry[]>>
> = {};

public async init() {
this.allFAQs = this.metaService.getAllFAQs();
this.allFAQs.set(this.metaService.getAllFAQs());

effect(
() => {
Expand All @@ -41,16 +51,23 @@ export class FAQService {
}

private loadLocaleFAQs(locale: string) {
this.allFAQs.forEach(async (faq) => {
const baseFAQs = this.faqByProductIdAndLocale();

this.allFAQs().forEach(async (faq) => {
if (faq.locale !== locale) return;
if (this.faqByProductIdAndLocale[faq.productId]?.[faq.locale]) return;
if (baseFAQs[faq.productId]?.[faq.locale]) return;

this.faqByProductIdAndLocale[faq.productId] ??= {};
baseFAQs[faq.productId] ??= {};

const faqData = await fetch(faq.url);
const realData = await faqData.json();

this.faqByProductIdAndLocale[faq.productId][faq.locale] = realData;
baseFAQs[faq.productId][faq.locale] = realData;

this.faqByProductIdAndLocale.set({
...this.faqByProductIdAndLocale(),
...baseFAQs,
});

realData.forEach((cardFAQ: ICardFAQ) => {
this.faqByProductLocaleCard[faq.productId] ??= {};
Expand All @@ -63,6 +80,34 @@ export class FAQService {
if (!this.isReady()) this.isReady.set(true);
}

public getFAQs(): Array<{
productId: string;
locale: string;
faq: ICardFAQ[];
}> {
if (!this.isReady()) return [];

const faqData = this.faqByProductIdAndLocale();
const locale = this.localeService.currentLocale();

return Object.keys(faqData)
.map((productId) => ({
productId,
locale,
faq: faqData[productId][locale],
}))
.filter((p) => p.faq)
.flat();
}

public getProductFAQ(
productId: string,
locale: string
): ICardFAQ[] | undefined {
const faq = this.faqByProductIdAndLocale();
return faq?.[productId]?.[locale];
}

public getCardFAQ(productId: string, card: string): ICardFAQEntry[] {
return (
this.faqByProductLocaleCard[productId]?.[
Expand Down
17 changes: 17 additions & 0 deletions src/app/faq/faq-routing.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { type Routes, RouterModule } from '@angular/router';

import { FaqPage } from './faq.page';

const routes: Routes = [
{
path: '',
component: FaqPage,
},
];

@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class FaqPageRoutingModule {}
22 changes: 22 additions & 0 deletions src/app/faq/faq.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { IonicModule } from '@ionic/angular';

import { FaqPageRoutingModule } from './faq-routing.module';

import { SharedModule } from '../_shared/shared.module';
import { FaqPage } from './faq.page';

@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
FaqPageRoutingModule,
SharedModule,
],
declarations: [FaqPage],
})
export class FaqPageModule {}
57 changes: 57 additions & 0 deletions src/app/faq/faq.page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<ion-header>
<app-topbar (enter)="search($event)"></app-topbar>
</ion-header>

<ion-content>
<div class="page-container">

@if(currentFAQ(); as faq) {
<ion-grid>
<ion-row>
<ion-col>
<ion-list>
@for(entry of faq; track $index) {
<ion-item-group>
<ion-item-divider>
<ion-label>{{ entry.card }}</ion-label>
</ion-item-divider>

@for(faqEntry of entry.faq; track $index) {
<ion-item>
<ion-label text-wrap>
<h3>Q: {{ faqEntry.q }}</h3>
<p>A: {{ faqEntry.a }}</p>
</ion-label>
</ion-item>
}
</ion-item-group>
}
</ion-list>
</ion-col>
</ion-row>
</ion-grid>
}

@else {
<ion-grid>
<ion-row>
@for(faq of faqs(); track $index) {
<ion-col size-lg="3" size-md="4" size-sm="6" size-xs="12">
<ion-card class="faq-tile" (click)="loadFAQ(faq)">
<ion-card-header>
<ion-card-title>{{ metaService.getProductNameByProductId(faq.productId) }}</ion-card-title>
</ion-card-header>

<ion-card-content>
{{ faq.faq.length | number }} FAQs
</ion-card-content>
</ion-card>
</ion-col>
}
</ion-row>
</ion-grid>
}
</div>

<app-below-the-fold></app-below-the-fold>
</ion-content>
22 changes: 22 additions & 0 deletions src/app/faq/faq.page.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.faq-tile {
min-height: 200px;
padding: 4px;

border: 2px solid #000;

cursor: pointer;
user-select: none;

&:hover {
border: 2px solid var(--ion-color-primary);
}

ion-card-content {
display: flex;
justify-content: center;
align-items: center;

font-size: 2em;
padding: 1em;
}
}
50 changes: 50 additions & 0 deletions src/app/faq/faq.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Component, computed, inject, signal } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import type { ICardFAQ } from '../../../interfaces';
import { FAQService } from '../faq.service';
import { MetaService } from '../meta.service';

@Component({
selector: 'app-faq',
templateUrl: './faq.page.html',
styleUrls: ['./faq.page.scss'],
})
export class FaqPage {
private router = inject(Router);
private route = inject(ActivatedRoute);
private faqService = inject(FAQService);
public metaService = inject(MetaService);

private locale = signal<string>('');
private productId = signal<string>('');

public faqs = computed(() => this.faqService.getFAQs());
public currentFAQ = computed(() =>
this.faqService.getProductFAQ(this.productId(), this.locale())
);

constructor() {}

ionViewDidEnter() {
this.locale.set(this.route.snapshot.queryParamMap.get('locale') ?? '');
this.productId.set(
this.route.snapshot.queryParamMap.get('productId') ?? ''
);

if (!this.locale() || !this.productId()) {
this.router.navigate(['/faq']);
return;
}
}

loadFAQ(faq: { productId: string; locale: string; faq: ICardFAQ[] }) {
this.router.navigate([], {
relativeTo: this.route,
queryParams: { locale: faq.locale, productId: faq.productId },
queryParamsHandling: 'merge',
});

this.locale.set(faq.locale);
this.productId.set(faq.productId);
}
}
4 changes: 2 additions & 2 deletions src/app/meta.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export class MetaService {
this.allProducts.forEach((product) => {
this.productNamesByProductId[product.id] = product.name;
this.templatesByProductId[product.id] = product.cardTemplate;
this.rulesByProductId[product.id] = product.external.rules;
this.rulesByProductId[product.id] = product.external?.rules ?? '';
this.filtersByProductId[product.id] = product.filters;
this.faqByProductId[product.id] = product.external.faq;
this.faqByProductId[product.id] = product.external?.faq ?? {};
});
}

Expand Down

0 comments on commit 486de79

Please sign in to comment.