Fluent Store Dashboard: new dashboard tile based on fulfilment expiry time
Author:
Randy Chan
Changed on:
16 Apr 2025
Key Points
- A guide to extend Fluent STORE UI capabilities to allow the store users to have a better visibility on the fulfilments by expiry time.
- The use case where the store staff would like to see number of fulfilments for the next 2 hours so that they can plan their pick and pack process accordingly.
- One of the solutions is by using OOTB component and manifest to display the fulfilments number based on the expiry time. Hence, there are no custom rules nor custom component is required for this solution.
- Here are the steps to archive the outcome:
- Create a new screen in fluent Store
- Create dashboard tiles
Prerequisites
Steps
Create a new screen in Fluent Store
Create a new for the new empty screen:
Name: fc...store.fragment.store_dashboard
Context:
Context ID: 0
Value Type: JSON
JSON Value:
1{
2 "manifestVersion": "2.0",
3 "routes": [
4 {
5 "type": "page",
6 "path": "store_dashboard",
7 "component": "fc.page",
8 "nav": {
9 "label": "Store Dashboard",
10 "icon": "store"
11 },
12 "props": {
13 "title": "Store Dashboard"
14 },
15 "descendants": []
16 }
17 ]
18}
Then add the new to the fc...store
1{
2 "type": "reference",
3 "settingName": "fc.mystique.manifest.store.fragment.store_dashboard"
4},

Refresh the store screen and you should able to see the new Store Dashboard page:


Create dashboard tiles
This step is to create 4 dashboard tiles where:
- Tile 1: display the number of (AWAITING_WAVE) fulfilments with the expiry Time is less than 30 mins.
- Tile 2: display the number of (AWAITING_WAVE) fulfilments with the expiry Time is between 30 and 60 mins.
- Tile 3: display the number of (AWAITING_WAVE) fulfilments with the expiry Time is between 60 and 120 mins.
- Tile 4: display the number of (AWAITING_WAVE) fulfilments assigned to this location.
Tile 1: Fulfilment expiring less than 30 mins
Parameter | Configuration |
Data Source |
|
Filters |
|
Min Threshold | 0 |
Max Threshold | 0 |
link | awaiting-pick page has a default filter of and status. Hence we only need to provide the fulfilments_expiryTime:
|
1{
2 "manifestVersion": "2.0",
3 "routes": [
4 {
5 "type": "page",
6 "path": "store_dashboard",
7 "component": "fc.page",
8 "nav": {
9 "label": "Store Dashboard",
10 "icon": "store"
11 },
12 "props": {
13 "title": "Store Dashboard"
14 },
15 "data": {
16 "query": "query ($ordersAwaitingPickFromLocationRef: String!, $ordersAwaitingPickStatus: [String]!, $fulfilmentExpiryNow:DateTime!, $fulfilmentExpiry30mins:DateTime!) { fulfilment_expired30Mins:fulfilments(fromLocation: {ref: $ordersAwaitingPickFromLocationRef}, status: $ordersAwaitingPickStatus, expiryTime:{from:$fulfilmentExpiryNow, to:$fulfilmentExpiry30mins}) { edges { node { id ref order { ref totalPrice customer { firstName lastName } } expiryTime deliveryType } } } }",
17 "variables": {
18 "ordersAwaitingPickFromLocationRef": "{{activeLocation.ref}}",
19 "ordersAwaitingPickStatus": [
20 "AWAITING_WAVE"
21 ],
22 "fulfilmentExpiryNow": "{{dateStringFormatter (dateAdd day=0) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}",
23 "fulfilmentExpiry30mins": "{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}"
24 }
25 },
26 "descendants": [
27 {
28 "component": "fc.dashboard.threshold",
29 "dataSource": "fulfilment_expired30Mins",
30 "props": {
31 "label": "i18n:fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired30Mins.title",
32 "subTitle": "Expiring in 30 mins",
33 "value": "{{edges.length}}",
34 "thresholdLow": 0,
35 "thresholdHigh": 0,
36 "width": "third",
37 "link": "#/waves/list/awaiting-pick?fulfilments_expiryTime={\"from\":\"{{dateStringFormatter (dateAdd day=0) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\",\"to\":\"{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\"}"
38 }
39 }
40 ]
41 }
42 ]
43}
Update the language :
1"fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired30Mins.title": "ORDER AWAITING PICK EXPIRING in 30 mins",
2"fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired60Mins.title": "ORDER AWAITING PICK EXPIRING in 60 mins",
3"fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired120Mins.title": "ORDER AWAITING PICK EXPIRING in 2 hours",
4

Refresh the Fluent Store screen:

Tile 2: Fulfilment expiring between 30 and 60 mins
Parameter | Configuration |
Data Source |
|
Filters |
|
Min Threshold | 1 |
Max Threshold | 10 |
link | awaiting-pick page has a default filter of and status. Hence we only need to provide the fulfilments_expiryTime:
|
1
2// 1. In the query section:
3//
4// 1.a Add a new parameter:
5, $fulfilmentExpiry60mins:DateTime!
6
7// 1.b add a new subquery:
8fulfilment_expired60Mins:fulfilments(fromLocation: {ref: $ordersAwaitingPickFromLocationRef}, status: $ordersAwaitingPickStatus, expiryTime:{from:$fulfilmentExpiry30mins, to:$fulfilmentExpiry60mins }) { edges { node { id ref order { ref totalPrice customer { firstName lastName } } expiryTime deliveryType } } }
9
10// 2. In the variables section:
11//
12,
13"fulfilmentExpiry60mins": "{{dateStringFormatter (dateAdd minute=60) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}"
14
15// 3. In the descendants section:
16,
17 {
18 "component": "fc.dashboard.threshold",
19 "dataSource": "fulfilment_expired60Mins",
20 "props": {
21 "label": "i18n:fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired60Mins.title",
22 "subTitle": "Expiring in 60 mins",
23 "value": "{{edges.length}}",
24 "thresholdLow": 1,
25 "thresholdHigh": 10,
26 "width": "third",
27 "link": "#/waves/list/awaiting-pick?fulfilments_expiryTime={\"from\":\"{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\",\"to\":\"{{dateStringFormatter (dateAdd minute=60) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\"}"
28 }
29 }
30
1{
2 "manifestVersion": "2.0",
3 "routes": [
4 {
5 "type": "page",
6 "path": "store_dashboard",
7 "component": "fc.page",
8 "nav": {
9 "label": "Store Dashboard",
10 "icon": "store"
11 },
12 "props": {
13 "title": "Store Dashboard"
14 },
15 "data": {
16 "query": "query ($ordersAwaitingPickFromLocationRef: String!, $ordersAwaitingPickStatus: [String]!, $fulfilmentExpiryNow:DateTime!, $fulfilmentExpiry30mins:DateTime!, $fulfilmentExpiry60mins:DateTime!) { fulfilment_expired30Mins:fulfilments(fromLocation: {ref: $ordersAwaitingPickFromLocationRef}, status: $ordersAwaitingPickStatus, expiryTime:{from:$fulfilmentExpiryNow, to:$fulfilmentExpiry30mins}) { edges { node { id ref order { ref totalPrice customer { firstName lastName } } expiryTime deliveryType } } } \n fulfilment_expired60Mins:fulfilments(fromLocation: {ref: $ordersAwaitingPickFromLocationRef}, status: $ordersAwaitingPickStatus, expiryTime:{from:$fulfilmentExpiry30mins, to:$fulfilmentExpiry60mins }) { edges { node { id ref order { ref totalPrice customer { firstName lastName } } expiryTime deliveryType } } } }",
17 "variables": {
18 "ordersAwaitingPickFromLocationRef": "{{activeLocation.ref}}",
19 "ordersAwaitingPickStatus": [
20 "AWAITING_WAVE"
21 ],
22 "fulfilmentExpiryNow": "{{dateStringFormatter (dateAdd day=0) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}",
23 "fulfilmentExpiry30mins": "{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}",
24 "fulfilmentExpiry60mins": "{{dateStringFormatter (dateAdd minute=60) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}"
25 }
26 },
27 "descendants": [
28 {
29 "component": "fc.dashboard.threshold",
30 "dataSource": "fulfilment_expired30Mins",
31 "props": {
32 "label": "i18n:fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired30Mins.title",
33 "subTitle": "Expiring in 30 mins",
34 "value": "{{edges.length}}",
35 "thresholdLow": 0,
36 "thresholdHigh": 0,
37 "width": "third",
38 "link": "#/waves/list/awaiting-pick?fulfilments_expiryTime={\"from\":\"{{dateStringFormatter (dateAdd day=0) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\",\"to\":\"{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\"}"
39 }
40 },
41 {
42 "component": "fc.dashboard.threshold",
43 "dataSource": "fulfilment_expired60Mins",
44 "props": {
45 "label": "i18n:fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired60Mins.title",
46 "subTitle": "Expiring in 60 mins",
47 "value": "{{edges.length}}",
48 "thresholdLow": 1,
49 "thresholdHigh": 10,
50 "width": "third",
51 "link": "#/waves/list/awaiting-pick?fulfilments_expiryTime={\"from\":\"{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\",\"to\":\"{{dateStringFormatter (dateAdd minute=60) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\"}"
52 }
53 }
54 ]
55 }
56 ]
57}
Refresh the Fluent Store:

Follow the same pattern as above for tile 3 (with expiryTime from:60mins and to:120mins) and for tile 4 expiryTime parameter does not require:
1{
2 "manifestVersion": "2.0",
3 "routes": [
4 {
5 "type": "page",
6 "path": "store_dashboard",
7 "component": "fc.page",
8 "nav": {
9 "label": "Store Dashboard",
10 "icon": "store"
11 },
12 "props": {
13 "title": "Store Dashboard"
14 },
15 "data": {
16 "query": "query ($ordersAwaitingPickFromLocationRef: String!, $ordersAwaitingPickStatus: [String]!, $fulfilmentExpiryNow:DateTime!, $fulfilmentExpiry30mins:DateTime!, $fulfilmentExpiry60mins:DateTime!, $fulfilmentExpiry120mins:DateTime!) { fulfilment_expired30Mins:fulfilments(fromLocation: {ref: $ordersAwaitingPickFromLocationRef}, status: $ordersAwaitingPickStatus, expiryTime:{from:$fulfilmentExpiryNow, to:$fulfilmentExpiry30mins}) { edges { node { id ref order { ref totalPrice customer { firstName lastName } } expiryTime deliveryType } } } \n fulfilment_expired60Mins:fulfilments(fromLocation: {ref: $ordersAwaitingPickFromLocationRef}, status: $ordersAwaitingPickStatus, expiryTime:{from:$fulfilmentExpiry30mins, to:$fulfilmentExpiry60mins }) { edges { node { id ref order { ref totalPrice customer { firstName lastName } } expiryTime deliveryType } } } \n fulfilment_expired120Mins:fulfilments(fromLocation: {ref: $ordersAwaitingPickFromLocationRef}, status: $ordersAwaitingPickStatus, expiryTime:{from:$fulfilmentExpiry60mins, to:$fulfilmentExpiry120mins }) { edges { node { id ref order { ref totalPrice customer { firstName lastName } } expiryTime deliveryType } } }\n fulfilment_awaitingwave:fulfilments(fromLocation: {ref: $ordersAwaitingPickFromLocationRef}, status: $ordersAwaitingPickStatus) { edges { node { id ref order { ref totalPrice customer { firstName lastName } } expiryTime deliveryType } } } \n }",
17 "variables": {
18 "ordersAwaitingPickFromLocationRef": "{{activeLocation.ref}}",
19 "ordersAwaitingPickStatus": [
20 "AWAITING_WAVE"
21 ],
22 "fulfilmentExpiryNow": "{{dateStringFormatter (dateAdd day=0) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}",
23 "fulfilmentExpiry30mins": "{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}",
24 "fulfilmentExpiry60mins": "{{dateStringFormatter (dateAdd minute=60) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}",
25 "fulfilmentExpiry120mins": "{{dateStringFormatter (dateAdd minute=120) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}"
26 }
27 },
28 "descendants": [
29 {
30 "component": "fc.dashboard.threshold",
31 "dataSource": "fulfilment_expired30Mins",
32 "props": {
33 "label": "i18n:fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired30Mins.title",
34 "subTitle": "Expiring in 30 mins",
35 "value": "{{edges.length}}",
36 "thresholdLow": 0,
37 "thresholdHigh": 0,
38 "width": "third",
39 "link": "#/waves/list/awaiting-pick?fulfilments_expiryTime={\"from\":\"{{dateStringFormatter (dateAdd day=0) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\",\"to\":\"{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\"}"
40 }
41 },
42 {
43 "component": "fc.dashboard.threshold",
44 "dataSource": "fulfilment_expired60Mins",
45 "props": {
46 "label": "i18n:fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired60Mins.title",
47 "subTitle": "Expiring in 60 mins",
48 "value": "{{edges.length}}",
49 "thresholdLow": 1,
50 "thresholdHigh": 10,
51 "width": "third",
52 "link": "#/waves/list/awaiting-pick?fulfilments_expiryTime={\"from\":\"{{dateStringFormatter (dateAdd minute=30) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\",\"to\":\"{{dateStringFormatter (dateAdd minute=60) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\"}"
53 }
54 },
55 {
56 "component": "fc.dashboard.threshold",
57 "dataSource": "fulfilment_expired120Mins",
58 "props": {
59 "label": "i18n:fc.sf.ui.waves.detail.dashboard.ordersAwaitingPickExpired120Mins.title",
60 "subTitle": "Expiring in 120 mins",
61 "value": "{{edges.length}}",
62 "thresholdLow": 1,
63 "thresholdHigh": 10,
64 "width": "third",
65 "link": "#/waves/list/awaiting-pick?fulfilments_expiryTime={\"from\":\"{{dateStringFormatter (dateAdd minute=60) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\",\"to\":\"{{dateStringFormatter (dateAdd minute=120) 'YYYY-MM-DD[T]HH:mm:ss.SSS' true}}Z\"}"
66 }
67 },
68 {
69 "component": "fc.dashboard.threshold",
70 "dataSource": "fulfilment_awaitingwave",
71 "props": {
72 "label": "i18n:fc.sf.ui.waves.detail.dashboard.ordersAwaitingPick.title",
73 "subTitle": "subTile text1",
74 "value": "{{edges.length}}",
75 "thresholdLow": 1,
76 "thresholdHigh": 10,
77 "width": "third"
78 }
79 }
80 ]
81 }
82 ]
83}

Except as otherwise stated in the Extend Knowledge Content site policy, the content on this page is licensed under the Creative Commons Attribution 4.0 Licence, and any code samples that appear on this page are licensed under the Apache 2.0 Licence, unless any code sample forms part of the Fluent Order Management Platform code. Neither of these licences apply to any content on any other page that can be reached via a link on this page unless otherwise specified on that other page. If you wish to use any of the Extend Knowledge Content, you must do so in compliance with the licenses referred to above and the Extend Knowledge Content site policy, including attribution in the manner set out on this page.