update pagination

This commit is contained in:
Kenta420-Poom 2023-09-25 15:29:42 +07:00
parent 3f399dda0e
commit 51642983c6
15 changed files with 1049 additions and 240 deletions

View file

@ -16,7 +16,6 @@
"@angular/platform-browser": "^16.2.0",
"@angular/platform-browser-dynamic": "^16.2.0",
"@angular/router": "^16.2.0",
"flowbite": "^1.8.1",
"jwt-decode": "^3.1.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
@ -29,6 +28,7 @@
"@types/google.accounts": "^0.0.9",
"@types/jasmine": "~4.3.0",
"autoprefixer": "^10.4.15",
"daisyui": "^3.7.7",
"jasmine-core": "~4.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@ -3122,15 +3122,6 @@
"node": ">=14"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@schematics/angular": {
"version": "16.2.2",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.2.tgz",
@ -4715,6 +4706,12 @@
"color-support": "bin.js"
}
},
"node_modules/colord": {
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
"integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
"dev": true
},
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
@ -5178,6 +5175,16 @@
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-selector-tokenizer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
"dev": true,
"dependencies": {
"cssesc": "^3.0.0",
"fastparse": "^1.1.2"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
@ -5232,6 +5239,26 @@
"integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==",
"dev": true
},
"node_modules/daisyui": {
"version": "3.7.7",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-3.7.7.tgz",
"integrity": "sha512-2/nFdW/6R9MMnR8tTm07jPVyPaZwpUSkVsFAADb7Oq8N2Ynbls57laDdNqxTCUmn0QvcZi01TKl8zQbAwRfw1w==",
"dev": true,
"dependencies": {
"colord": "^2.9",
"css-selector-tokenizer": "^0.8",
"postcss": "^8",
"postcss-js": "^4",
"tailwindcss": "^3"
},
"engines": {
"node": ">=16.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/daisyui"
}
},
"node_modules/data-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
@ -6091,6 +6118,12 @@
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true
},
"node_modules/fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
"dev": true
},
"node_modules/fastq": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
@ -6219,15 +6252,6 @@
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
"node_modules/flowbite": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/flowbite/-/flowbite-1.8.1.tgz",
"integrity": "sha512-lXTcO8a6dRTPFpINyOLcATCN/pK1Of/jY4PryklPllAiqH64tSDUsOdQpar3TO59ZXWwugm2e92oaqwH6X90Xg==",
"dependencies": {
"@popperjs/core": "^2.9.3",
"mini-svg-data-uri": "^1.4.3"
}
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
@ -8332,14 +8356,6 @@
"webpack": "^5.0.0"
}
},
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"bin": {
"mini-svg-data-uri": "cli.js"
}
},
"node_modules/minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",

View file

@ -18,7 +18,6 @@
"@angular/platform-browser": "^16.2.0",
"@angular/platform-browser-dynamic": "^16.2.0",
"@angular/router": "^16.2.0",
"flowbite": "^1.8.1",
"jwt-decode": "^3.1.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
@ -31,6 +30,7 @@
"@types/google.accounts": "^0.0.9",
"@types/jasmine": "~4.3.0",
"autoprefixer": "^10.4.15",
"daisyui": "^3.7.7",
"jasmine-core": "~4.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@ -41,4 +41,4 @@
"tailwindcss": "^3.3.3",
"typescript": "~5.1.3"
}
}
}

View file

@ -1,7 +1,7 @@
import { NgModule, inject } from '@angular/core';
import { CanActivateFn, Router, RouterModule, Routes } from '@angular/router';
import { UserService } from './core/services/user.service';
import { Subject, finalize, lastValueFrom, map, takeUntil } from 'rxjs';
import { lastValueFrom, map } from 'rxjs';
const authGuard: CanActivateFn = () => {
const userService: UserService = inject(UserService);
@ -74,12 +74,6 @@ const routes: Routes = [
},
],
},
{
path: '**',
pathMatch: 'full',
redirectTo: 'dashboard',
},
];
@NgModule({

View file

@ -1,6 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { initFlowbite } from 'flowbite';
@Component({
selector: 'app-root',
@ -12,6 +11,5 @@ export class AppComponent implements OnInit {
ngOnInit(): void {
this.titleService.setTitle('Recipe Manager | Tao Bin');
initFlowbite();
}
}

View file

@ -9,7 +9,6 @@
type="button"
class="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200"
>
<span class="sr-only">Open sidebar</span>
<svg
class="w-6 h-6"
aria-hidden="true"
@ -52,63 +51,66 @@
{{ user?.name }}
</span>
</div>
<button
type="button"
class="flex text-sm bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300 max-sm:hidden"
aria-expanded="false"
data-dropdown-toggle="dropdown-user"
>
<span class="sr-only">Open user menu</span>
<img
class="sm:h-10 md:h-14 rounded-full cursor-pointer"
src="{{ user?.picture }}"
loading="lazy"
alt="profile picture"
/>
</button>
<div class="dropdown dropdown-bottom dropdown-end">
<label
tabindex="0"
class="btn btn-circle w-14 h-14 focus:ring ring-primary ring-offset-base-100 ring-offset-2 max-sm:hidden"
>
<div class="avatar">
<div class="rounded-full">
<img src="{{ user?.picture }}" alt="profile picture" />
</div>
</div>
</label>
<div
tabindex="0"
class="dropdown-content z-[-1] menu p-2 shadow bg-base-100 rounded-box w-52 divide-y divide-gray-100"
>
<div class="px-4 py-3" role="none">
<p class="text-sm text-gray-900" role="none">
{{ user?.name }}
</p>
<p
class="text-sm font-medium text-gray-900 truncate"
role="none"
>
{{ user?.email }}
</p>
</div>
<ul class="py-1" role="none">
<li>
<a
routerLink="/dashboard"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
role="menuitem"
>
Dashboard</a
>
</li>
<li>
<a
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
role="menuitem"
>Settings</a
>
</li>
<li>
<a
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
role="menuitem"
(click)="logout()"
>Sign out</a
>
</li>
</ul>
</div>
</div>
</div>
<div
class="z-50 hidden my-4 text-base list-none bg-primary divide-y divide-gray-100 rounded shadow"
id="dropdown-user"
>
<div class="px-4 py-3" role="none">
<p class="text-sm text-gray-900" role="none">
{{ user?.name }}
</p>
<p class="text-sm font-medium text-gray-900 truncate" role="none">
{{ user?.email }}
</p>
</div>
<ul class="py-1" role="none">
<li>
<a
routerLink="/dashboard"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
role="menuitem"
>
Dashboard</a
>
</li>
<li>
<a
href="#"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
role="menuitem"
>Settings</a
>
</li>
<li>
<a
routerLink="#"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
role="menuitem"
(click)="logout()"
>Sign out</a
>
</li>
</ul>
</div>
></div>
</div>
</div>
</div>

View file

@ -4,7 +4,6 @@ import { DatePipe, NgFor, NgIf } from '@angular/common';
import { GoogleButtonComponent } from 'src/app/shared/googleButton/googleButton.component';
import { UserService } from '../services/user.service';
import { User } from '../models/user.model';
import { initFlowbite } from 'flowbite';
import { Subject, takeUntil } from 'rxjs';
interface MenuItem {
@ -40,8 +39,6 @@ export class LayoutComponent implements OnInit {
constructor(private _userService: UserService) {}
ngOnInit(): void {
initFlowbite();
this._userService.currentUser
.pipe(takeUntil(this.exit$))
.subscribe((user) => (this.user = user));

View file

@ -4,12 +4,27 @@ import { BehaviorSubject, Observable, distinctUntilChanged } from 'rxjs';
import { Recipe } from '../models/recipe.model';
import { environment } from 'src/environments/environment';
interface Pagination {
offset: number;
take: number;
}
@Injectable({ providedIn: 'root' })
export class RecipeService {
constructor(private _httpClient: HttpClient) {}
getRecipes(): Observable<Recipe> {
return this._httpClient.get<Recipe>(environment.api + '/recipes', {
getRecipes(paginate: Pagination = { take: 10, offset: 0 }): Observable<{
recipes: Recipe;
hasMore: boolean;
}> {
return this._httpClient.get<{
recipes: Recipe;
hasMore: boolean;
}>(environment.api + '/recipes', {
params: {
offset: String(paginate.offset),
take: String(paginate.take),
},
withCredentials: true,
});
}

View file

@ -1,49 +1,72 @@
<main class="relative overflow-auto max-h-[700px] shadow-md sm:rounded-lg">
<table
*ngIf="isLoaded; else loadingIndicator"
class="w-full table-auto text-sm text-left text-gray-500"
>
<caption
class="p-5 text-lg font-semibold text-left text-gray-900 bg-primary"
>
<div class="flex flex-row">
<div class="flex flex-col">
<span
>Recipe Version {{ recipes?.MachineSetting?.configNumber }} |
{{"{{File name}}"}}</span
>
<main
class="relative overflow-auto max-h-[700px] shadow-md sm:rounded-lg"
#table
>
<table *ngIf="isLoaded" class="table">
<caption class="p-5 text-lg font-semibold text-left text-gray-900">
<div class="divide-y divide-solid divide-gray-400">
<div class="flex flex-row py-3">
<div class="flex flex-col">
<span
>Recipe Version {{ recipes?.MachineSetting?.configNumber }} |
{{"{{File name}}"}}</span
>
</div>
<div class="flex flex-col ml-auto">
<span class=""
>Last Updated:
{{ recipes?.Timestamp | date : "dd-MMM-yyyy hh:mm:ss" }}</span
>
</div>
</div>
<div class="flex flex-col ml-auto">
<span class=""
>Last Updated:
{{ recipes?.Timestamp | date : "dd-MMM-yyyy hh:mm:ss" }}</span
>
<div class="flex flex-col">
<div class="relativ sm:rounded-lg">
<div
class="flex flex-col items-center justify-between p-4 space-y-3 md:flex-row md:space-y-0 md:space-x-4"
>
<div class="join">
<input
class="input input-bordered join-item w-[300px]"
placeholder="Product Code, Name or Other Name"
/>
<button class="btn join-item">Search</button>
</div>
<div class="flex gap-2">
<button class="btn rounded-lg">View JSON</button>
<button class="btn rounded-lg">
<svg
class="w-6 h-6 text-gray-800 dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 18 20"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1"
d="M15 6V2a.97.97 0 0 0-.933-1H5.828a2 2 0 0 0-1.414.586L1.586 4.414A2 2 0 0 0 1 5.828V18a.969.969 0 0 0 .933 1H14a1 1 0 0 0 1-1M6 1v4a1 1 0 0 1-1 1H1m6 6h9m-1.939-2.768L16.828 12l-2.767 2.768"
/>
</svg>
Export
</button>
</div>
</div>
</div>
</div>
</div>
</caption>
<thead class="text-xs sticky top-0 text-gray-700 uppercase bg-secondary">
<tr>
<th scope="col" class="px-6 py-3" *ngFor="let head of tableHeads">
<th>
<label>
<input type="checkbox" class="checkbox" />
</label>
</th>
<th scope="col" class="px-6 py-3" *ngFor="let header of tableHeads">
<div class="flex items-center uppercase">
{{ head }}
<a href="#"
><svg
class="w-3 h-3 ml-1.5"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
>
<path
d="M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z"
/>
</svg>
</a>
</div>
</th>
<th scope="col" class="flex items-center py-3">
<div class="flex items-center text-center uppercase">
Actions
{{ header }}
<a href="#"
><svg
class="w-3 h-3 ml-1.5"
@ -59,52 +82,65 @@
</a>
</div>
</th>
<th scope="col" class="px-6 py-3"></th>
</tr>
</thead>
<tbody>
<tr
*ngFor="let recipe of recipes!.Recipe01"
*ngFor="let recipe of recipes01"
class="bg-white la border-b hover:bg-secondary"
>
<th
<th>
<label>
<input type="checkbox" class="checkbox" />
</label>
</th>
<td
scope="row"
class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap"
>
{{ recipe.productCode }}
</td>
<td
class="px-6 max-w-fit py-4 font-medium text-gray-900 whitespace-nowrap"
>
{{ recipe.name }}
</th>
</td>
<td class="px-6 py-4">{{ recipe.otherName }}</td>
<td class="px-6 py-4 flex-wrap max-w-xs">{{ recipe.Description }}</td>
<td class="px-6 py-4">
{{ recipe.LastChange | date : "dd-MMM-yyyy hh:mm:ss" }}
</td>
<td class="px-6 py-4 flex gap-2">
<a
href="#"
class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>Edit</a
>
<a
href="#"
class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>Edit</a
>
<a
href="#"
class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>Edit</a
>
<td class="px-4 py-4 flex">
<div class="cursor-pointer">
<svg
class="w-6 h-6 text-gray-800 dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 20 20"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1"
d="M7.75 4H19M7.75 4a2.25 2.25 0 0 1-4.5 0m4.5 0a2.25 2.25 0 0 0-4.5 0M1 4h2.25m13.5 6H19m-2.25 0a2.25 2.25 0 0 1-4.5 0m4.5 0a2.25 2.25 0 0 0-4.5 0M1 10h11.25m-4.5 6H19M7.75 16a2.25 2.25 0 0 1-4.5 0m4.5 0a2.25 2.25 0 0 0-4.5 0M1 16h2.25"
/>
</svg>
</div>
</td>
</tr>
</tbody>
</table>
<ng-template #loadingIndicator>
<div *ngIf="!isLoaded">
<div
class="flex w-full items-center justify-center h-56 border border-gray-200 rounded-lg bg-gray-50"
>
<div role="status">
<svg
aria-hidden="true"
class="w-8 h-8 mr-2 text-gray-200 animate-spin fill-blue-600"
class="w-8 h-8 mr-2 text-gray-200 animate-spin fill-amber-600"
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
@ -120,67 +156,5 @@
</svg>
</div>
</div>
</ng-template>
</div>
</main>
<nav
class="flex items-center justify-between pt-4"
aria-label="Table navigation"
>
<span class="text-sm font-normal text-gray-500 dark:text-gray-400"
>Showing
<span class="font-semibold text-gray-900 dark:text-white">1-10</span> of
<span class="font-semibold text-gray-900 dark:text-white">1000</span></span
>
<ul class="inline-flex -space-x-px text-sm h-8">
<li>
<a
href="#"
class="flex items-center justify-center px-3 h-8 ml-0 leading-tight text-gray-500 bg-white border border-gray-300 rounded-l-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
>Previous</a
>
</li>
<li>
<a
href="#"
class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
>1</a
>
</li>
<li>
<a
href="#"
class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
>2</a
>
</li>
<li>
<a
href="#"
aria-current="page"
class="flex items-center justify-center px-3 h-8 text-blue-600 border border-gray-300 bg-blue-50 hover:bg-blue-100 hover:text-blue-700 dark:border-gray-700 dark:bg-gray-700 dark:text-white"
>3</a
>
</li>
<li>
<a
href="#"
class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
>4</a
>
</li>
<li>
<a
href="#"
class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
>5</a
>
</li>
<li>
<a
href="#"
class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 rounded-r-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
>Next</a
>
</li>
</ul>
</nav>

View file

@ -1,13 +1,19 @@
import { Component, OnInit } from '@angular/core';
import {
AfterContentChecked,
AfterRenderRef,
AfterViewChecked,
AfterViewInit,
Component,
ElementRef,
OnInit,
ViewChild,
} from '@angular/core';
import { UserService } from 'src/app/core/services/user.service';
import { HttpClient } from '@angular/common/http';
import { User } from 'src/app/core/models/user.model';
import { DatePipe, NgFor, NgIf } from '@angular/common';
import { initFlowbite } from 'flowbite';
import { environment } from 'src/environments/environment';
import { delay } from 'rxjs';
import { Recipe } from 'src/app/core/models/recipe.model';
import { Recipe, Recipe01 } from 'src/app/core/models/recipe.model';
import { RecipeService } from 'src/app/core/services/recipe.service';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'app-dashboard',
@ -18,8 +24,59 @@ import { RecipeService } from 'src/app/core/services/recipe.service';
export class DashboardComponent implements OnInit {
userInfo: User | null = null;
recipes: Recipe | null = null;
tableHeads: string[] = ['Name', 'Other Name', 'Description', 'Last Updated'];
recipes01: Recipe01[] | null = null;
tableHeads: string[] = [
'Product Code',
'Name',
'Other Name',
'Description',
'Last Updated',
];
private offset = 0;
private take = 10;
isLoaded: boolean = false;
isLoadMore: boolean = false;
isHasMore: boolean = true;
@ViewChild('table', { static: false }) set content(table: ElementRef) {
table.nativeElement.addEventListener(
'scroll',
() => {
if (this.isHasMore === false) {
return;
}
const { scrollTop, scrollHeight, clientHeight } = table.nativeElement;
const isBottom = scrollTop + clientHeight >= scrollHeight - 10;
if (isBottom && !this.isLoadMore) {
this.isLoadMore = true;
this._recipeService
.getRecipes({
offset: this.offset,
take: this.take,
})
.subscribe(({ recipes, hasMore }) => {
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
if (this.recipes01 && this.isHasMore) {
this.recipes01 = [...this.recipes01, ...Recipe01];
} else {
this.recipes01 = Recipe01;
}
this.recipes = {
...recipesWithoutRecipe01,
Recipe01: [],
};
this.offset += 10;
this.isLoadMore = false;
this.isHasMore = hasMore;
});
}
},
{ passive: true }
);
}
constructor(
private _userService: UserService,
@ -27,16 +84,29 @@ export class DashboardComponent implements OnInit {
) {}
ngOnInit(): void {
initFlowbite();
this._userService.currentUser.subscribe((user) => {
this.userInfo = user;
});
this._recipeService.getRecipes().subscribe((recipes) => {
this.recipes = recipes;
this.isLoaded = true;
console.log(this.recipes);
});
this._recipeService
.getRecipes({
offset: this.offset,
take: this.take,
})
.subscribe(({ recipes, hasMore }) => {
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
if (this.recipes01 && this.isHasMore) {
this.recipes01 = [...this.recipes01, ...Recipe01];
} else {
this.recipes01 = Recipe01;
}
this.recipes = {
...recipesWithoutRecipe01,
Recipe01: [],
};
this.offset += 10;
this.isLoaded = true;
this.isHasMore = hasMore;
});
}
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M240-40q-33 0-56.5-23.5T160-120v-440q0-33 23.5-56.5T240-640h120v80H240v440h480v-440H600v-80h120q33 0 56.5 23.5T800-560v440q0 33-23.5 56.5T720-40H240Zm200-280v-447l-64 64-56-57 160-160 160 160-56 57-64-64v447h-80Z"/></svg>

After

Width:  |  Height:  |  Size: 318 B

View file

@ -1,14 +1,15 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: "class",
content: [
"./src/**/*.{html,ts}",
"./node_modules/flowbite/**/*.js" // add this line
],
theme: {
extend: {
"backgroundColor": {
"primary": "#EAE6E1",
"secondary": "#F5F5F5",
"third": "#F2994A",
},
"textColor": {
"primary": "#513C2F",
@ -18,6 +19,9 @@ module.exports = {
}
},
},
plugins: [require("flowbite/plugin")],
daisyui: {
themes: ["cupcake"]
},
plugins: [require('daisyui')],
}