diff --git a/uniquely/flight-finder-pwa/l10n/fa-IR.json b/uniquely/flight-finder-pwa/l10n/fa-IR.json
index a1f728707..6130bb2d3 100644
--- a/uniquely/flight-finder-pwa/l10n/fa-IR.json
+++ b/uniquely/flight-finder-pwa/l10n/fa-IR.json
@@ -5,7 +5,7 @@
"flight_finder": "پرواز یاب",
"search_list": "لیست جستجو",
- "seconds_ago": "ثانیه پیش",
+ "minutes_ago": "دقیقه پیش",
"origin": "مبدا",
"destination": "مقصد",
"confirm": "تایید",
diff --git a/uniquely/flight-finder-pwa/src/component/job-add-form.ts b/uniquely/flight-finder-pwa/src/component/job-add-form.ts
index 5c006339b..0541349e7 100644
--- a/uniquely/flight-finder-pwa/src/component/job-add-form.ts
+++ b/uniquely/flight-finder-pwa/src/component/job-add-form.ts
@@ -99,7 +99,7 @@ export class JobAddForm extends AlwatrElement {
${l10n.localize('origin')}
diff --git a/uniquely/flight-finder-pwa/src/component/job-item.ts b/uniquely/flight-finder-pwa/src/component/job-item.ts
index 67fc3322e..3296b826d 100644
--- a/uniquely/flight-finder-pwa/src/component/job-item.ts
+++ b/uniquely/flight-finder-pwa/src/component/job-item.ts
@@ -79,6 +79,11 @@ export class JobItem extends AlwatrElement {
.job .job__subtitle .job__subtitle-price {
color: var(--ion-color-base);
}
+
+ ion-item-options {
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ }
`,
];
diff --git a/uniquely/flight-finder-pwa/src/component/page-flight-finder.ts b/uniquely/flight-finder-pwa/src/component/page-flight-finder.ts
index cb7ef21cf..dfa7ed044 100644
--- a/uniquely/flight-finder-pwa/src/component/page-flight-finder.ts
+++ b/uniquely/flight-finder-pwa/src/component/page-flight-finder.ts
@@ -3,7 +3,7 @@ import {l10n} from '@alwatr/i18n';
import {SignalInterface} from '@alwatr/signal';
import {modalController} from '@ionic/core';
import {css, html} from 'lit';
-import {customElement} from 'lit/decorators.js';
+import {customElement, query} from 'lit/decorators.js';
import {map} from 'lit/directives/map.js';
import ionNormalize from '../style/ionic.normalize.js';
@@ -42,6 +42,11 @@ export class PageFlightFinder extends AlwatrElement {
justify-content: center;
}
+ #timer {
+ display: inline-block;
+ min-width: 23px;
+ }
+
.version {
direction: ltr;
margin: 0 16px 8px;
@@ -50,11 +55,27 @@ export class PageFlightFinder extends AlwatrElement {
`,
];
- private __jobList: Array = [];
-
- static jobListSignal = new SignalInterface('job-list');
+ static jobDocumentStorageSignal = new SignalInterface('job-document-storage');
static jobAddSignal = new SignalInterface('job-add');
+ private __jobList?: Array;
+ private __lastUpdate = 0;
+ @query('#timer') protected _timer?: HTMLSpanElement;
+
+ constructor() {
+ super();
+ this.__updateTimer = this.__updateTimer.bind(this);
+ }
+
+ private __updateTimer(): void {
+ const timer = this._timer;
+ if (timer == null || this.__lastUpdate === 0) return;
+
+ const time = Math.floor((Date.now() - this.__lastUpdate) / 6_000) / 10;
+
+ timer.innerText = l10n.formatNumber(time);
+ }
+
override connectedCallback(): void {
super.connectedCallback();
@@ -62,10 +83,13 @@ export class PageFlightFinder extends AlwatrElement {
this.requestUpdate();
});
- PageFlightFinder.jobListSignal.addListener((jobList) => {
- this.__jobList = jobList;
+ PageFlightFinder.jobDocumentStorageSignal.addListener((jobList) => {
+ this.__jobList = Object.values(jobList.data);
+ this.__lastUpdate = jobList.meta.lastUpdated;
this.requestUpdate();
});
+
+ setInterval(this.__updateTimer, 3_000);
}
override render(): TemplateResult {
return html`
@@ -84,7 +108,7 @@ export class PageFlightFinder extends AlwatrElement {
- v${Alwatr.version}-prv3
+ v${Alwatr.version}-prv4
`;
}
@@ -94,7 +118,7 @@ export class PageFlightFinder extends AlwatrElement {
${l10n.localize('search_list')}
- ۵ ${l10n.localize('seconds_ago')}
+ - ${l10n.localize('minutes_ago')}
@@ -113,7 +137,6 @@ export class PageFlightFinder extends AlwatrElement {
modal.dismiss();
});
-
await modal.present();
}
}
diff --git a/uniquely/flight-finder-pwa/src/director/index.ts b/uniquely/flight-finder-pwa/src/director/index.ts
index 884183416..aab96cb94 100644
--- a/uniquely/flight-finder-pwa/src/director/index.ts
+++ b/uniquely/flight-finder-pwa/src/director/index.ts
@@ -1,4 +1,4 @@
-import './job-add';
-import './job-delete';
-import './job-list.js';
+import './job-add.js';
+import './job-delete.js';
+import './job-document-storage.js';
import './toast.js';
diff --git a/uniquely/flight-finder-pwa/src/director/job-add.ts b/uniquely/flight-finder-pwa/src/director/job-add.ts
index 43c4eae20..bb3904c77 100644
--- a/uniquely/flight-finder-pwa/src/director/job-add.ts
+++ b/uniquely/flight-finder-pwa/src/director/job-add.ts
@@ -1,7 +1,7 @@
import {fetch} from '@alwatr/fetch';
import {SignalInterface} from '@alwatr/signal';
-import {jobListSignal} from './job-list.js';
+import {jobDocumentStorageSignal} from './job-document-storage.js';
import {showToastSignal} from './toast.js';
import type {Job} from '../type.js';
@@ -34,5 +34,5 @@ jobAddSignal.addListener(async (job) => {
});
}
- jobListSignal.request(null);
+ jobDocumentStorageSignal.request(null);
});
diff --git a/uniquely/flight-finder-pwa/src/director/job-delete.ts b/uniquely/flight-finder-pwa/src/director/job-delete.ts
index 6c98da671..89ce99f2e 100644
--- a/uniquely/flight-finder-pwa/src/director/job-delete.ts
+++ b/uniquely/flight-finder-pwa/src/director/job-delete.ts
@@ -1,7 +1,7 @@
import {fetch} from '@alwatr/fetch';
import {SignalInterface} from '@alwatr/signal';
-import {jobListSignal} from './job-list.js';
+import {jobDocumentStorageSignal} from './job-document-storage.js';
import {showToastSignal} from './toast.js';
import type {AlwatrServiceResponse} from '@alwatr/fetch';
@@ -33,5 +33,5 @@ jobDeleteSignal.addListener(async (id) => {
});
}
- jobListSignal.request(null);
+ jobDocumentStorageSignal.request(null);
});
diff --git a/uniquely/flight-finder-pwa/src/director/job-document-storage.ts b/uniquely/flight-finder-pwa/src/director/job-document-storage.ts
new file mode 100644
index 000000000..ccae37e4d
--- /dev/null
+++ b/uniquely/flight-finder-pwa/src/director/job-document-storage.ts
@@ -0,0 +1,40 @@
+import {serviceRequest} from '@alwatr/fetch';
+import {AlwatrDocumentStorage, CacheStrategy} from '@alwatr/fetch/src/type.js';
+import {createLogger} from '@alwatr/logger';
+import {SignalInterface} from '@alwatr/signal';
+
+import {showToastSignal} from './toast.js';
+
+import type {Job} from '../type.js';
+
+export const logger = createLogger('[director/job-document-storage]');
+export const jobDocumentStorageSignal = new SignalInterface('job-document-storage');
+
+async function requestJobStorage(cacheStrategy: CacheStrategy): Promise {
+ logger.logMethod('jobListProvider');
+
+ try {
+ jobDocumentStorageSignal.dispatch(
+ > await serviceRequest({
+ url: window.appConfig?.api ? window.appConfig.api + '/job' : '/job',
+ token: window.appConfig?.token,
+ cache: 'no-cache',
+ cacheStrategy,
+ }),
+ );
+ }
+ catch (error) {
+ if ((error as Error).message !== 'fetch_cache_not_found') {
+ logger.error('jobListProvider', 'fetch_failed', error);
+ showToastSignal.dispatch({
+ message: 'عملیات با خطا رو به رو شد',
+ });
+ }
+ }
+}
+
+jobDocumentStorageSignal.setProvider(() => requestJobStorage('network_first'));
+
+requestJobStorage('cache_only').then(() => requestJobStorage('network_first'));
+
+setInterval(() => jobDocumentStorageSignal.request(null), 60_000);
diff --git a/uniquely/flight-finder-pwa/src/director/job-list.ts b/uniquely/flight-finder-pwa/src/director/job-list.ts
deleted file mode 100644
index a9dd2316a..000000000
--- a/uniquely/flight-finder-pwa/src/director/job-list.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import {fetch} from '@alwatr/fetch';
-import {SignalInterface} from '@alwatr/signal';
-
-import {showToastSignal} from './toast.js';
-
-import type {Job} from '../type.js';
-import type {AlwatrServiceResponse} from '@alwatr/fetch';
-
-export const jobListSignal = new SignalInterface('job-list');
-
-async function _dispatchJobList(response: Response): Promise {
- if (response.ok !== true) {
- throw new Error('fetch_failed');
- }
-
- const responseData = (await response.json()) as AlwatrServiceResponse>;
-
- if (responseData.ok !== true) {
- throw new Error('fetch_failed');
- }
-
- jobListSignal.dispatch(Object.values(responseData.data));
-}
-
-jobListSignal.setProvider(async () => {
- try {
- const response = await fetch({
- url: window.appConfig?.api ? window.appConfig.api + '/job' : '/job',
- token: window.appConfig?.token,
- cacheStrategy: 'stale_while_revalidate',
- revalidateCallback(response) {
- _dispatchJobList(response);
- },
- cache: 'no-cache',
- });
-
- await _dispatchJobList(response);
- }
- catch (error) {
- showToastSignal.dispatch({
- message: 'عملیات با خطا رو به رو شد',
- });
- }
- return;
-});
-
-jobListSignal.request(null);
-setInterval(()=>jobListSignal.request(null), 60_000);
diff --git a/uniquely/flight-finder-pwa/src/type.ts b/uniquely/flight-finder-pwa/src/type.ts
index 644a3cd91..2d2feea29 100644
--- a/uniquely/flight-finder-pwa/src/type.ts
+++ b/uniquely/flight-finder-pwa/src/type.ts
@@ -1,4 +1,4 @@
-import type {AlwatrDocumentObject} from '@alwatr/fetch';
+import type {AlwatrDocumentObject, AlwatrDocumentStorage} from '@alwatr/fetch/type.js';
import type {ToastOptions} from '@ionic/core';
declare global {
@@ -8,11 +8,11 @@ declare global {
interface AlwatrSignals {
readonly 'job-add': Pick;
readonly 'job-delete': string;
- readonly 'job-list': Array;
+ readonly 'job-document-storage': AlwatrDocumentStorage;
readonly toast: Partial & {message: string};
}
interface AlwatrRequestSignals {
- readonly 'job-list': null;
+ readonly 'job-document-storage': null;
}
}
@@ -42,8 +42,8 @@ export type JobResult = {
price: number;
time: string;
seatCount: number;
- airline: string,
- airplane: string,
- flightId: string,
- arrivalTime: string,
+ airline: string;
+ airplane: string;
+ flightId: string;
+ arrivalTime: string;
};