Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a home page #11

Merged
merged 10 commits into from
Aug 25, 2024
373 changes: 0 additions & 373 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ export const routes: Routes = [
path: 'settings',
loadChildren: () => import('./settings/settings.routes').then(m => m.settingsRoutes),
},
{ path: '', redirectTo: '/planting', pathMatch: 'full' },
{
path: '',
loadChildren: () => import('./home/home.routes').then(m => m.homeRoutes),
},

// rest
{ path: '**', redirectTo: '/' },
];
25 changes: 4 additions & 21 deletions src/app/cultivating/cultivating-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/cor

import { BarnService } from '../barn/barn.service';
import { LearnCardsComponent } from '../learning/learn-cards.component';
import { DialogComponent } from '../ui/dialog/dialog.component';
import { SproutDetailsComponent, type SproutDetailsSprout } from './sprout-details/sprout-details.component';
import { SproutDetailsDialogComponent } from './sprout-details-dialog/sprout-details-dialog.component';
import { type SproutDetailsSprout } from './sprout-details/sprout-details.component';
import { SproutsListComponent } from './sprouts-list/sprouts-list.component';

@Component({
Expand All @@ -15,18 +15,11 @@ import { SproutsListComponent } from './sprouts-list/sprouts-list.component';
<app-sprouts-list [sprouts]="sprouts() ?? []" (showDetails)="onShowDetails($event)" />

@if (sproutDetails(); as sprout) {
<app-dialog (close)="sproutDetails.set(null)">
<app-sprout-details
[sprout]="sprout"
(cancel)="sproutDetails.set(null)"
(remove)="onRemoveSprout(sprout.id)"
(update)="onUpdateSprout(sprout.id, $event)"
/>
</app-dialog>
<app-sprout-details-dialog [sprout]="sprout" (close)="sproutDetails.set(null)" />
}
</div>
`,
imports: [SproutsListComponent, SproutDetailsComponent, DialogComponent, LearnCardsComponent],
imports: [SproutsListComponent, SproutDetailsDialogComponent, LearnCardsComponent],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
})
Expand All @@ -45,14 +38,4 @@ export class CultivatingPageComponent {

this.sproutDetails.set(sprout);
}

onRemoveSprout(id: string) {
this.barnService.removeSprout(id);
this.sproutDetails.set(null);
}

onUpdateSprout(id: string, value: Partial<SproutDetailsSprout>) {
this.barnService.updateSprout(id, value);
this.sproutDetails.set(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ChangeDetectionStrategy, Component, inject, input, output } from '@angular/core';

import { BarnService } from '../../barn/barn.service';
import { DialogComponent } from '../../ui/dialog/dialog.component';
import { SproutDetailsComponent, type SproutDetailsSprout } from '../sprout-details/sprout-details.component';

@Component({
selector: 'app-sprout-details-dialog',
template: `
<app-dialog (close)="close.emit()">
<app-sprout-details
[sprout]="sprout()"
(cancel)="close.emit()"
(remove)="onRemoveSprout(sprout().id)"
(update)="onUpdateSprout(sprout().id, $event)"
/>
</app-dialog>
`,
imports: [DialogComponent, SproutDetailsComponent],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SproutDetailsDialogComponent {
private barnService = inject(BarnService);

sprout = input.required<SproutDetailsSprout>();

close = output();

onRemoveSprout(id: string) {
this.barnService.removeSprout(id);
this.close.emit();
}

onUpdateSprout(id: string, value: Partial<SproutDetailsSprout>) {
this.barnService.updateSprout(id, value);
this.close.emit();
}
}
23 changes: 23 additions & 0 deletions src/app/home/add-terms-button/add-terms-button.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';

import { IconComponent } from '../../ui/icon/icon';
import { AddTermsDialogComponent } from '../add-terms-dialog/add-terms-dialog.component';

@Component({
selector: 'app-add-terms-button',
template: `
<button class="fixed bottom-16 right-6" title="Add" (click)="showAddTermsDialog.set(true)">
<app-icon class="size-10 text-action-primary" name="plusInCircle" />
</button>

@if (showAddTermsDialog()) {
<app-add-terms-dialog (close)="showAddTermsDialog.set(false)" />
}
`,
imports: [IconComponent, AddTermsDialogComponent],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AddTermsButtonComponent {
showAddTermsDialog = signal(false);
}
56 changes: 56 additions & 0 deletions src/app/home/add-terms-dialog/add-terms-dialog.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { ChangeDetectionStrategy, Component, inject, output, signal } from '@angular/core';

import { BarnService } from '../../barn/barn.service';
import { ButtonDirective } from '../../ui/button/button';
import { DialogComponent } from '../../ui/dialog/dialog.component';
import { InputDirective } from '../../ui/input/input';

@Component({
selector: 'app-add-terms-dialog',
template: `
<app-dialog (close)="close.emit()">
<div class="flex h-full flex-col gap-8 pt-10">
<textarea
class="grow"
appInput
placeholder="One seed a line"
autocapitalize="off"
[value]="newSeed()"
(input)="updateSeed($event)"
></textarea>

<div class="mt-auto flex shrink-0 justify-end gap-4">
<button appButton (click)="close.emit()">Cancel</button>
<button appButton appButtonType="primary" (click)="add()">Add</button>
</div>
</div>
</app-dialog>
`,
imports: [DialogComponent, ButtonDirective, InputDirective],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AddTermsDialogComponent {
private barnService = inject(BarnService);

close = output();

newSeed = signal('');

updateSeed(event: Event) {
this.newSeed.set((event.target as HTMLTextAreaElement).value);
}

add() {
const newSeeds = this.newSeed()
.split('\n')
.map(seed => seed.trim())
.filter(seed => !!seed);

if (newSeeds.length !== 0) {
this.barnService.addSeeds(newSeeds);
}

this.close.emit();
}
}
25 changes: 25 additions & 0 deletions src/app/home/home-page.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { LearnCardsComponent } from '../learning/learn-cards.component';
import { AddTermsButtonComponent } from './add-terms-button/add-terms-button.component';
import { LastSeedsListComponent } from './last-seeds-list/last-seeds-list.component';
import { UnsortedSproutsComponent } from './unsorted-sprouts/unsorted-sprouts.component';

@Component({
selector: 'app-home-page',
template: `
<div class="flex flex-col gap-4">
<app-unsorted-sprouts />

<app-learn-cards />

<app-last-seeds-list />

<app-add-terms-button />
</div>
`,
imports: [UnsortedSproutsComponent, LearnCardsComponent, AddTermsButtonComponent, LastSeedsListComponent],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HomePageComponent {}
9 changes: 9 additions & 0 deletions src/app/home/home.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Routes } from '@angular/router';

export const homeRoutes: Routes = [
{
path: '',
title: 'Akker',
loadComponent: () => import('./home-page.component').then(m => m.HomePageComponent),
},
];
35 changes: 35 additions & 0 deletions src/app/home/last-seeds-list/last-seeds-list.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core';

import { BarnService } from '../../barn/barn.service';

@Component({
selector: 'app-last-seeds-list',
template: `
<section>
<h2 class="text-lg text-secondary">Last seeds</h2>

<ul class="columns-2 gap-4">
@for (seed of lastAddedSeeds(); track seed.name) {
<li class="w-full truncate px-2 py-1">
{{ seed.name }}
</li>
}
</ul>
</section>
`,
imports: [],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LastSeedsListComponent {
private barnService = inject(BarnService);

lastAddedSeeds = computed(() =>
this.barnService
.seeds()
?.toSorted((a, b) => b.lastAddedAt.localeCompare(a.lastAddedAt))
.slice(0, lastSeedsCount),
);
}

const lastSeedsCount = 10;
44 changes: 44 additions & 0 deletions src/app/home/unsorted-sprouts/unsorted-sprouts.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';

import { BarnService } from '../../barn/barn.service';
import { SproutDetailsDialogComponent } from '../../cultivating/sprout-details-dialog/sprout-details-dialog.component';
import { type SproutDetailsSprout } from '../../cultivating/sprout-details/sprout-details.component';

@Component({
selector: 'app-unsorted-sprouts',
template: `
@if (someUnsortedSprouts().length > 0) {
<section class="min-w-0 flex-grow">
<h2 class="text-lg text-secondary">Unsorted sprouts ({{ unsortedSproutsAmount() }})</h2>

<ul class="columns-2 gap-4">
@for (sprout of someUnsortedSprouts(); track sprout.id) {
<li>
<button class="w-full truncate px-2 py-1 text-left" (click)="sproutDetails.set(sprout)">
{{ sprout.term }}
</button>
</li>
}
</ul>
</section>

@if (sproutDetails(); as sprout) {
<app-sprout-details-dialog [sprout]="sprout" (close)="sproutDetails.set(null)" />
}
}
`,
imports: [SproutDetailsDialogComponent],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UnsortedSproutsComponent {
private barnService = inject(BarnService);
private unsortedSprouts = computed(() => this.barnService.sprouts()?.filter(sprout => !sprout.definition));

unsortedSproutsAmount = computed(() => this.unsortedSprouts()?.length ?? 0);
someUnsortedSprouts = computed(() => this.unsortedSprouts()?.slice(0, someUnsortedSproutsAmount) ?? []);

sproutDetails = signal<SproutDetailsSprout | null>(null);
}

const someUnsortedSproutsAmount = 10;
26 changes: 14 additions & 12 deletions src/app/layout/layout.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ import { RouterLink, RouterLinkActive } from '@angular/router';
selector: 'app-layout',
template: `
<div class="flex h-dvh flex-col overflow-hidden bg-primary text-primary">
<main class="grow overflow-y-auto p-5">
<main class="relative grow overflow-y-auto p-5">
<ng-content />
</main>

<nav class="shrink-0 border-t border-primary/10 px-2">
<ul class="flex justify-between gap-2">
@for (link of navigationLinks; track link.path) {
<li>
<!-- TODO: fix important usage -->
<a class="block p-3 text-secondary" [routerLink]="link.path" routerLinkActive="!text-primary">
{{ link.label }}
</a>
</li>
}
</ul>
<nav class="flex shrink-0 justify-between gap-2 border-t border-primary/10 px-2">
@for (link of navigationLinks; track link.path) {
<!-- TODO: fix important usage -->
<a
class="block p-3 text-secondary"
[routerLink]="link.path"
routerLinkActive="!text-primary"
[routerLinkActiveOptions]="link.options ?? { exact: false }"
>
{{ link.label }}
</a>
}
</nav>
</div>
`,
Expand All @@ -29,6 +30,7 @@ import { RouterLink, RouterLinkActive } from '@angular/router';
})
export class LayoutComponent {
navigationLinks = [
{ path: '/', label: 'Home', options: { exact: true } },
{ path: '/planting', label: 'Planting' },
{ path: '/cultivating', label: 'Cultivating' },
{ path: '/settings', label: 'Settings' },
Expand Down
3 changes: 0 additions & 3 deletions src/app/planting/new-seed/assets/input.svg

This file was deleted.

3 changes: 0 additions & 3 deletions src/app/planting/new-seed/assets/multiline-input.svg

This file was deleted.

Loading