MME-34 Remove tanstack from recipe upload page and ai-or-manual step.

This commit is contained in:
Jesse Brault 2026-02-19 18:11:38 -06:00
parent 907c8c34ad
commit e1479f6078
5 changed files with 61 additions and 31 deletions

View File

@ -15,7 +15,6 @@ import { tryMaybeInt } from '../../shared/util';
import { from, map, switchMap, tap } from 'rxjs';
import { Review } from './steps/review/review';
import { RecipeEditFormSubmitEvent } from '../../shared/components/recipe-edit-form/RecipeEditFormSubmitEvent';
import { QueryClient } from '@tanstack/angular-query-experimental';
import { ToastrService } from 'ngx-toastr';
@Component({
@ -37,7 +36,6 @@ export class RecipeUploadPage implements OnInit {
private readonly router = inject(Router);
private readonly activatedRoute = inject(ActivatedRoute);
private readonly recipeDraftService = inject(RecipeDraftService);
private readonly queryClient = inject(QueryClient);
private readonly toastrService = inject(ToastrService);
private isValidStep(step: number): boolean {
@ -163,9 +161,6 @@ export class RecipeUploadPage implements OnInit {
protected async onDeleteDraft(): Promise<void> {
await this.recipeDraftService.deleteDraft(this.model().draft!.id);
await this.queryClient.invalidateQueries({
queryKey: ['recipe-upload', 'in-progress-drafts'],
});
await this.switchModel(
{
inProgressStep: RecipeUploadStep.START,

View File

@ -0,0 +1,18 @@
.in-progress-draft-link,
.in-progress-draft-list-item {
display: flex;
column-gap: 5px;
align-items: baseline;
}
.in-progress-draft-link * {
cursor: pointer;
}
.last-saved {
font-size: 0.8em;
}
.no-title {
font-style: italic;
}

View File

@ -1,19 +1,24 @@
<section>
<h2>Start</h2>
<section>
@if (inProgressDrafts.isLoading()) {
<p>Loading drafts...</p>
} @else if (inProgressDrafts.isError()) {
<p>Could not fetch drafts!</p>
} @else if (inProgressDrafts.isSuccess() && inProgressDrafts.data().length) {
@if (loadingDrafts()) {
<app-spinner></app-spinner>
} @else if (drafts().length) {
<h3>In Progress Drafts</h3>
<ul>
@for (draft of inProgressDrafts.data(); track draft.id) {
<li>
<a (click)="onInProgressDraftClick(draft)">
@for (draft of drafts(); track $index) {
<li class="in-progress-draft-list-item">
<a class="in-progress-draft-link" (click)="onInProgressDraftClick(draft)">
<fa-icon [icon]="faFilePen"></fa-icon>
{{ draft.title }}
@if (draft.title) {
<span>{{ draft.title }}</span>
} @else {
<span class="no-title">(No title)</span>
}
</a>
<span class="last-saved"
>(Last saved {{ (draft.modified ? draft.modified : draft.created) | date: "short" }})</span
>
</li>
}
</ul>

View File

@ -1,29 +1,32 @@
import { Component, computed, inject, input, output } from '@angular/core';
import { Component, computed, inject, input, OnInit, output, signal } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { ReactiveFormsModule } from '@angular/forms';
import { AIOrManualSubmitEvent } from './AIOrManualSubmitEvent';
import { FileUpload } from '../../../../shared/components/file-upload/file-upload';
import { FileUploadEvent } from '../../../../shared/components/file-upload/FileUploadEvent';
import { injectQuery } from '@tanstack/angular-query-experimental';
import { RecipeDraftService } from '../../../../shared/services/RecipeDraftService';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { faFilePen } from '@fortawesome/free-solid-svg-icons';
import { Router } from '@angular/router';
import { RecipeDraftViewModel } from '../../../../shared/models/RecipeDraftView.model';
import { Spinner } from '../../../../shared/components/spinner/spinner';
import { ToastrService } from 'ngx-toastr';
import { DatePipe } from '@angular/common';
@Component({
selector: 'app-ai-or-manual',
imports: [MatButton, ReactiveFormsModule, FileUpload, FaIconComponent],
imports: [MatButton, ReactiveFormsModule, FileUpload, FaIconComponent, Spinner, DatePipe],
templateUrl: './ai-or-manual.html',
styleUrl: './ai-or-manual.css',
})
export class AiOrManual {
export class AiOrManual implements OnInit {
public sourceFile = input.required<File | null>();
public sourceFileChange = output<FileUploadEvent>();
public submitStep = output<AIOrManualSubmitEvent>();
private readonly recipeDraftService = inject(RecipeDraftService);
private readonly router = inject(Router);
private readonly toastrService = inject(ToastrService);
protected readonly sourceFilesArray = computed(() => {
const maybeSourceFile = this.sourceFile();
@ -34,12 +37,23 @@ export class AiOrManual {
}
});
protected readonly inProgressDrafts = injectQuery(() => ({
queryKey: ['recipe-upload', 'in-progress-drafts'],
queryFn: () => {
return this.recipeDraftService.getInProgressDrafts();
},
}));
protected readonly loadingDrafts = signal(false);
protected readonly drafts = signal<RecipeDraftViewModel[]>([]);
public ngOnInit(): void {
this.loadingDrafts.set(true);
this.recipeDraftService.getInProgressDrafts().subscribe({
next: (drafts) => {
this.loadingDrafts.set(false);
this.drafts.set(drafts);
},
error: (e) => {
this.loadingDrafts.set(false);
console.error(e);
this.toastrService.error('There was an error Recipe drafts');
},
});
}
protected onFileChange(event: FileUploadEvent) {
this.sourceFileChange.emit(event);

View File

@ -34,13 +34,11 @@ export class RecipeDraftService {
};
}
public getInProgressDrafts(): Promise<RecipeDraftViewModel[]> {
return firstValueFrom(
this.http.get<WithStringDates<RecipeDraftViewModel>[]>(this.endpointService.getUrl('recipeDrafts')).pipe(
map((rawViews) => {
return rawViews.map((rawView) => this.hydrateView(rawView));
}),
),
public getInProgressDrafts(): Observable<RecipeDraftViewModel[]> {
return this.http.get<WithStringDates<RecipeDraftViewModel>[]>(this.endpointService.getUrl('recipeDrafts')).pipe(
map((rawViews) => {
return rawViews.map((rawView) => this.hydrateView(rawView));
}),
);
}