@fleetbase/storefront-engine 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +32 -0
  3. package/addon/adapters/addon-category.js +1 -0
  4. package/addon/adapters/customer.js +1 -0
  5. package/addon/adapters/gateway.js +1 -0
  6. package/addon/adapters/network.js +1 -0
  7. package/addon/adapters/notification-channel.js +1 -0
  8. package/addon/adapters/product-addon-category.js +1 -0
  9. package/addon/adapters/product-addon.js +1 -0
  10. package/addon/adapters/product-hour.js +1 -0
  11. package/addon/adapters/product-store-location.js +1 -0
  12. package/addon/adapters/product-variant-option.js +1 -0
  13. package/addon/adapters/product-variant.js +1 -0
  14. package/addon/adapters/product.js +1 -0
  15. package/addon/adapters/store-hour.js +1 -0
  16. package/addon/adapters/store-location.js +1 -0
  17. package/addon/adapters/store.js +1 -0
  18. package/addon/adapters/storefront.js +5 -0
  19. package/addon/components/file-record.hbs +22 -0
  20. package/addon/components/file-record.js +43 -0
  21. package/addon/components/modals/add-store-hours.hbs +8 -0
  22. package/addon/components/modals/add-stores-to-network.hbs +5 -0
  23. package/addon/components/modals/assign-driver.hbs +25 -0
  24. package/addon/components/modals/create-first-store.hbs +21 -0
  25. package/addon/components/modals/create-gateway.hbs +35 -0
  26. package/addon/components/modals/create-network-category.hbs +50 -0
  27. package/addon/components/modals/create-network.hbs +20 -0
  28. package/addon/components/modals/create-new-variant.hbs +15 -0
  29. package/addon/components/modals/create-notification-channel.hbs +45 -0
  30. package/addon/components/modals/create-product-category.hbs +30 -0
  31. package/addon/components/modals/create-store.hbs +9 -0
  32. package/addon/components/modals/edit-network.hbs +1 -0
  33. package/addon/components/modals/import-products.hbs +97 -0
  34. package/addon/components/modals/incoming-order.hbs +242 -0
  35. package/addon/components/modals/manage-addons.hbs +50 -0
  36. package/addon/components/modals/manage-addons.js +86 -0
  37. package/addon/components/modals/order-ready-assign-driver.hbs +36 -0
  38. package/addon/components/modals/select-addon-category.hbs +5 -0
  39. package/addon/components/modals/share-network.hbs +35 -0
  40. package/addon/components/modals/store-location-form.hbs +30 -0
  41. package/addon/components/order-card.hbs +1 -0
  42. package/addon/components/order-card.js +3 -0
  43. package/addon/components/schedule-manager.hbs +22 -0
  44. package/addon/components/schedule-manager.js +73 -0
  45. package/addon/components/settings-container.hbs +7 -0
  46. package/addon/components/store-selector.hbs +21 -0
  47. package/addon/components/store-selector.js +20 -0
  48. package/addon/components/widget/customers.hbs +44 -0
  49. package/addon/components/widget/customers.js +53 -0
  50. package/addon/components/widget/orders.hbs +111 -0
  51. package/addon/components/widget/orders.js +248 -0
  52. package/addon/components/widget/storefront-metrics.hbs +54 -0
  53. package/addon/components/widget/storefront-metrics.js +61 -0
  54. package/addon/controllers/application.js +33 -0
  55. package/addon/controllers/customers/index.js +267 -0
  56. package/addon/controllers/home.js +3 -0
  57. package/addon/controllers/networks/index/network/customers.js +3 -0
  58. package/addon/controllers/networks/index/network/index.js +147 -0
  59. package/addon/controllers/networks/index/network/orders.js +3 -0
  60. package/addon/controllers/networks/index/network/stores.js +370 -0
  61. package/addon/controllers/networks/index/network.js +29 -0
  62. package/addon/controllers/networks/index.js +138 -0
  63. package/addon/controllers/orders/index.js +331 -0
  64. package/addon/controllers/products/index/category/edit.js +62 -0
  65. package/addon/controllers/products/index/category/new.js +287 -0
  66. package/addon/controllers/products/index/category.js +163 -0
  67. package/addon/controllers/products/index/index/edit.js +1 -0
  68. package/addon/controllers/products/index/index.js +136 -0
  69. package/addon/controllers/products/index.js +203 -0
  70. package/addon/controllers/settings/api.js +3 -0
  71. package/addon/controllers/settings/gateways.js +110 -0
  72. package/addon/controllers/settings/index.js +102 -0
  73. package/addon/controllers/settings/locations.js +186 -0
  74. package/addon/controllers/settings/notifications.js +102 -0
  75. package/addon/engine.js +19 -0
  76. package/addon/helpers/get-tip-amount.js +5 -0
  77. package/addon/models/addon-category.js +6 -0
  78. package/addon/models/gateway.js +46 -0
  79. package/addon/models/network.js +166 -0
  80. package/addon/models/notification-channel.js +47 -0
  81. package/addon/models/product-addon-category.js +41 -0
  82. package/addon/models/product-addon.js +41 -0
  83. package/addon/models/product-hour.js +72 -0
  84. package/addon/models/product-store-location.js +41 -0
  85. package/addon/models/product-variant-option.js +39 -0
  86. package/addon/models/product-variant.js +44 -0
  87. package/addon/models/product.js +208 -0
  88. package/addon/models/store-hour.js +72 -0
  89. package/addon/models/store-location.js +93 -0
  90. package/addon/models/store.js +100 -0
  91. package/addon/routes/application.js +47 -0
  92. package/addon/routes/customers/index/edit.js +3 -0
  93. package/addon/routes/customers/index.js +25 -0
  94. package/addon/routes/home.js +3 -0
  95. package/addon/routes/networks/index/network/customers.js +3 -0
  96. package/addon/routes/networks/index/network/index.js +15 -0
  97. package/addon/routes/networks/index/network/orders.js +3 -0
  98. package/addon/routes/networks/index/network/stores.js +28 -0
  99. package/addon/routes/networks/index/network.js +10 -0
  100. package/addon/routes/networks/index.js +19 -0
  101. package/addon/routes/orders/index/edit.js +3 -0
  102. package/addon/routes/orders/index/new.js +3 -0
  103. package/addon/routes/orders/index/view.js +3 -0
  104. package/addon/routes/orders/index.js +29 -0
  105. package/addon/routes/products/index/category/edit.js +15 -0
  106. package/addon/routes/products/index/category/new.js +7 -0
  107. package/addon/routes/products/index/category.js +54 -0
  108. package/addon/routes/products/index/index/edit.js +1 -0
  109. package/addon/routes/products/index/index.js +22 -0
  110. package/addon/routes/products/index.js +21 -0
  111. package/addon/routes/settings/api.js +10 -0
  112. package/addon/routes/settings/gateways.js +11 -0
  113. package/addon/routes/settings/index.js +16 -0
  114. package/addon/routes/settings/locations.js +14 -0
  115. package/addon/routes/settings/notifications.js +11 -0
  116. package/addon/routes.js +48 -0
  117. package/addon/serializers/addon-category.js +15 -0
  118. package/addon/serializers/network.js +19 -0
  119. package/addon/serializers/notification-channel.js +15 -0
  120. package/addon/serializers/product-addon-category.js +15 -0
  121. package/addon/serializers/product-variant.js +15 -0
  122. package/addon/serializers/product.js +20 -0
  123. package/addon/serializers/store-location.js +17 -0
  124. package/addon/serializers/store.js +19 -0
  125. package/addon/services/storefront.js +208 -0
  126. package/addon/templates/application.hbs +16 -0
  127. package/addon/templates/customers/index/edit.hbs +2 -0
  128. package/addon/templates/customers/index.hbs +22 -0
  129. package/addon/templates/home.hbs +7 -0
  130. package/addon/templates/networks/index/network/customers.hbs +2 -0
  131. package/addon/templates/networks/index/network/index.hbs +254 -0
  132. package/addon/templates/networks/index/network/orders.hbs +2 -0
  133. package/addon/templates/networks/index/network/stores.hbs +164 -0
  134. package/addon/templates/networks/index/network.hbs +38 -0
  135. package/addon/templates/networks/index.hbs +60 -0
  136. package/addon/templates/orders/index/edit.hbs +2 -0
  137. package/addon/templates/orders/index/new.hbs +2 -0
  138. package/addon/templates/orders/index/view.hbs +2 -0
  139. package/addon/templates/orders/index.hbs +22 -0
  140. package/addon/templates/products/index/category/edit.hbs +1 -0
  141. package/addon/templates/products/index/category/new.hbs +248 -0
  142. package/addon/templates/products/index/category.hbs +41 -0
  143. package/addon/templates/products/index/index/edit.hbs +1 -0
  144. package/addon/templates/products/index/index.hbs +40 -0
  145. package/addon/templates/products/index.hbs +22 -0
  146. package/addon/templates/settings/api.hbs +18 -0
  147. package/addon/templates/settings/gateways.hbs +48 -0
  148. package/addon/templates/settings/index.hbs +229 -0
  149. package/addon/templates/settings/locations.hbs +39 -0
  150. package/addon/templates/settings/notifications.hbs +35 -0
  151. package/addon/templates/settings.hbs +30 -0
  152. package/addon/utils/get-gateway-schemas.js +34 -0
  153. package/addon/utils/get-notification-schemas.js +18 -0
  154. package/app/adapters/addon-category.js +1 -0
  155. package/app/adapters/gateway.js +1 -0
  156. package/app/adapters/network.js +1 -0
  157. package/app/adapters/notification-channel.js +1 -0
  158. package/app/adapters/product-addon-category.js +1 -0
  159. package/app/adapters/product-addon.js +1 -0
  160. package/app/adapters/product-hour.js +1 -0
  161. package/app/adapters/product-store-location.js +1 -0
  162. package/app/adapters/product-variant-option.js +1 -0
  163. package/app/adapters/product-variant.js +1 -0
  164. package/app/adapters/product.js +1 -0
  165. package/app/adapters/store-hour.js +1 -0
  166. package/app/adapters/store-location.js +1 -0
  167. package/app/adapters/store.js +1 -0
  168. package/app/adapters/storefront.js +1 -0
  169. package/app/components/file-record.js +1 -0
  170. package/app/components/modals/add-store-hours.js +1 -0
  171. package/app/components/modals/add-stores-to-network.js +1 -0
  172. package/app/components/modals/assign-driver.js +1 -0
  173. package/app/components/modals/create-first-store.js +1 -0
  174. package/app/components/modals/create-gateway.js +1 -0
  175. package/app/components/modals/create-network-category.js +1 -0
  176. package/app/components/modals/create-network.js +1 -0
  177. package/app/components/modals/create-new-variant.js +1 -0
  178. package/app/components/modals/create-notification-channel.js +1 -0
  179. package/app/components/modals/create-product-category.js +1 -0
  180. package/app/components/modals/create-store.js +1 -0
  181. package/app/components/modals/edit-network.js +1 -0
  182. package/app/components/modals/import-products.js +1 -0
  183. package/app/components/modals/incoming-order.js +1 -0
  184. package/app/components/modals/manage-addons.js +1 -0
  185. package/app/components/modals/order-ready-assign-driver.js +1 -0
  186. package/app/components/modals/select-addon-category.js +1 -0
  187. package/app/components/modals/share-network.js +1 -0
  188. package/app/components/modals/store-location-form.js +1 -0
  189. package/app/components/order-card.js +1 -0
  190. package/app/components/schedule-manager.js +1 -0
  191. package/app/components/settings-container.js +1 -0
  192. package/app/components/store-selector.js +1 -0
  193. package/app/components/widget/customers.js +1 -0
  194. package/app/components/widget/orders.js +1 -0
  195. package/app/components/widget/storefront-metrics.js +1 -0
  196. package/app/controllers/application.js +1 -0
  197. package/app/controllers/customers/index.js +1 -0
  198. package/app/controllers/home.js +1 -0
  199. package/app/controllers/networks/index/network/customers.js +1 -0
  200. package/app/controllers/networks/index/network/index.js +1 -0
  201. package/app/controllers/networks/index/network/orders.js +1 -0
  202. package/app/controllers/networks/index/network/stores.js +1 -0
  203. package/app/controllers/networks/index/network.js +1 -0
  204. package/app/controllers/networks/index.js +1 -0
  205. package/app/controllers/orders/index.js +1 -0
  206. package/app/controllers/products/index/category/edit.js +1 -0
  207. package/app/controllers/products/index/category/new.js +1 -0
  208. package/app/controllers/products/index/category.js +1 -0
  209. package/app/controllers/products/index/index/edit.js +1 -0
  210. package/app/controllers/products/index/index.js +1 -0
  211. package/app/controllers/products/index.js +1 -0
  212. package/app/controllers/settings/api.js +1 -0
  213. package/app/controllers/settings/gateways.js +1 -0
  214. package/app/controllers/settings/index.js +1 -0
  215. package/app/controllers/settings/locations.js +1 -0
  216. package/app/controllers/settings/notifications.js +1 -0
  217. package/app/helpers/get-tip-amount.js +1 -0
  218. package/app/models/addon-category.js +1 -0
  219. package/app/models/gateway.js +1 -0
  220. package/app/models/network.js +1 -0
  221. package/app/models/notification-channel.js +1 -0
  222. package/app/models/product-addon-category.js +1 -0
  223. package/app/models/product-addon.js +1 -0
  224. package/app/models/product-hour.js +1 -0
  225. package/app/models/product-store-location.js +1 -0
  226. package/app/models/product-variant-option.js +1 -0
  227. package/app/models/product-variant.js +1 -0
  228. package/app/models/product.js +1 -0
  229. package/app/models/store-hour.js +1 -0
  230. package/app/models/store-location.js +1 -0
  231. package/app/models/store.js +1 -0
  232. package/app/routes/application.js +1 -0
  233. package/app/routes/customers/index/edit.js +1 -0
  234. package/app/routes/customers/index.js +1 -0
  235. package/app/routes/home.js +1 -0
  236. package/app/routes/networks/index/network/customers.js +1 -0
  237. package/app/routes/networks/index/network/index.js +1 -0
  238. package/app/routes/networks/index/network/orders.js +1 -0
  239. package/app/routes/networks/index/network/stores.js +1 -0
  240. package/app/routes/networks/index/network.js +1 -0
  241. package/app/routes/networks/index.js +1 -0
  242. package/app/routes/orders/index/edit.js +1 -0
  243. package/app/routes/orders/index/new.js +1 -0
  244. package/app/routes/orders/index/view.js +1 -0
  245. package/app/routes/orders/index.js +1 -0
  246. package/app/routes/products/index/category/edit.js +1 -0
  247. package/app/routes/products/index/category/new.js +1 -0
  248. package/app/routes/products/index/category.js +1 -0
  249. package/app/routes/products/index/index/edit.js +1 -0
  250. package/app/routes/products/index/index.js +1 -0
  251. package/app/routes/products/index.js +1 -0
  252. package/app/routes/settings/api.js +1 -0
  253. package/app/routes/settings/gateways.js +1 -0
  254. package/app/routes/settings/index.js +1 -0
  255. package/app/routes/settings/locations.js +1 -0
  256. package/app/routes/settings/notifications.js +1 -0
  257. package/app/serializers/addon-category.js +1 -0
  258. package/app/serializers/network.js +1 -0
  259. package/app/serializers/notification-channel.js +1 -0
  260. package/app/serializers/product-addon-category.js +1 -0
  261. package/app/serializers/product-variant.js +1 -0
  262. package/app/serializers/product.js +1 -0
  263. package/app/serializers/store-location.js +1 -0
  264. package/app/serializers/store.js +1 -0
  265. package/app/services/storefront.js +1 -0
  266. package/app/templates/customers/index/edit.js +1 -0
  267. package/app/templates/customers/index.js +1 -0
  268. package/app/templates/home.js +1 -0
  269. package/app/templates/networks/index/network/customers.js +1 -0
  270. package/app/templates/networks/index/network/index.js +1 -0
  271. package/app/templates/networks/index/network/orders.js +1 -0
  272. package/app/templates/networks/index/network/stores.js +1 -0
  273. package/app/templates/networks/index/network.js +1 -0
  274. package/app/templates/networks/index.js +1 -0
  275. package/app/templates/orders/index/edit.js +1 -0
  276. package/app/templates/orders/index/new.js +1 -0
  277. package/app/templates/orders/index/view.js +1 -0
  278. package/app/templates/orders/index.js +1 -0
  279. package/app/templates/products/index/category/edit.js +1 -0
  280. package/app/templates/products/index/category/new.js +1 -0
  281. package/app/templates/products/index/category.js +1 -0
  282. package/app/templates/products/index/index/edit.js +1 -0
  283. package/app/templates/products/index/index.js +1 -0
  284. package/app/templates/products/index.js +1 -0
  285. package/app/templates/settings/api.js +1 -0
  286. package/app/templates/settings/gateways.js +1 -0
  287. package/app/templates/settings/index.js +1 -0
  288. package/app/templates/settings/locations.js +1 -0
  289. package/app/templates/settings/notifications.js +1 -0
  290. package/app/templates/settings.js +1 -0
  291. package/app/utils/get-gateway-schemas.js +1 -0
  292. package/app/utils/get-notification-schemas.js +1 -0
  293. package/config/environment.js +21 -0
  294. package/index.js +22 -0
  295. package/package.json +123 -0
  296. package/pnpm-lock.yaml +12509 -0
@@ -0,0 +1,242 @@
1
+ <Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
2
+ <div class="mt-4">
3
+ <div class="py-1">
4
+ <div class="flex flex-col items-center justify-center">
5
+ <div class="p-2 rounded-md bg-white">
6
+ <img src={{concat "data:image/png;base64," @options.order.tracking_number.qr_code}} class="w-18 h-18" alt={{@options.order.public_id}} />
7
+ </div>
8
+ <div class="my-2.5 text-center">
9
+ <h2 class="dark:text-gray-100 font-semibold">{{@options.order.public_id}}</h2>
10
+ </div>
11
+ </div>
12
+ </div>
13
+ <div class="w-full my-2">
14
+ <div class="flex px-6 py-4 border-t border-b border-gray-100 dark:border-gray-800">
15
+ <h5 class="dark:text-gray-100 font-semibold">Store</h5>
16
+ </div>
17
+ <div class="flex items-start px-6 py-2">
18
+ <img src={{@options.store.logo_url}} class="w-12 h-12 rounded-md shadow-sm mr-4" alt={{@options.store.name}} />
19
+ <div>
20
+ <h5 class="font-semibold dark:text-white text-base">{{@options.store.name}}</h5>
21
+ <DisplayPlace @place={{@options.order.payload.pickup}} @type="store location" @addressClass="text-sm dark:text-gray-100" @noAddressClass="text-sm" />
22
+ </div>
23
+ </div>
24
+ </div>
25
+ <div class="w-full my-2">
26
+ <div class="flex px-6 py-4 border-t border-b border-gray-100 dark:border-gray-800">
27
+ <h5 class="dark:text-gray-100 font-semibold">Driver Assigned</h5>
28
+ </div>
29
+ <div class="flex flex-col px-6 py-2">
30
+ {{#if @options.order.driver_assigned.id}}
31
+ <div class="flex items-center">
32
+ <img src={{@options.order.driver_assigned.photoUrl}} class="w-12 h-12 rounded-md shadow-sm mr-4" alt={{@options.order.driver_assigned.name}} />
33
+ <div>
34
+ <h5 class="font-semibold dark:text-white text-base">{{n-a @options.order.driver_assigned.displayName}}</h5>
35
+ <div class="font-semibold dark:text-gray-100 text-sm">{{n-a @options.order.driver_assigned.phone "No phone"}}</div>
36
+ </div>
37
+ </div>
38
+ {{else}}
39
+ <h5 class="text-red-500 text-sm">No driver assigned</h5>
40
+ {{/if}}
41
+ {{#if @options.assignDriver}}
42
+ <div class="mt-2.5">
43
+ <Button @size="xs" @type="default" @icon="steering-wheel" @text={{if @options.order.has_driver_assigned "Change Driver" "Assign Driver"}} @onClick={{@options.assignDriver}} />
44
+ </div>
45
+ {{/if}}
46
+ </div>
47
+ </div>
48
+ <div class="w-full my-2">
49
+ <div class="flex px-6 py-4 border-t border-b border-gray-100 dark:border-gray-800">
50
+ <div class="flex-1">
51
+ {{#if @options.order.meta.is_pickup}}
52
+ <h5 class="dark:text-gray-100 font-semibold">Pickup</h5>
53
+ {{else}}
54
+ <h5 class="dark:text-gray-100 font-semibold">Delivery</h5>
55
+ {{/if}}
56
+ </div>
57
+ </div>
58
+ <div class="py-2 px-6">
59
+ <div class="flex">
60
+ {{#if @options.order.meta.is_pickup}}
61
+ <div class="flex-1">
62
+ <div class="rounded-md bg-blue-50 mr-4">
63
+ <div class="rounded-t-md bg-blue-100 px-3 py-2 mb-3">
64
+ <span class="text-blue-500 font-semibold text-sm truncate">Customer must pickup order from</span>
65
+ </div>
66
+ <div class="flex flex-row items-center mb-4 pb-4 px-3">
67
+ <div class="flex items-center justify-center rounded-full bg-blue-500 w-8 h-8 mr-3">
68
+ <FaIcon @icon="store-alt" class="text-white" />
69
+ </div>
70
+ <div class="text-xs text-blue-900 truncate">
71
+ <DisplayPlace @place={{@options.order.payload.pickup}} @type="pickup" />
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ {{else if @options.order.payload.hasWaypoints}}
77
+ <RouteList @order={{@options.order}} />
78
+ {{else}}
79
+ <div class="order-route-list storefront flex-1">
80
+ <div class="order-route-stop">
81
+ <div class="order-route-stop-index">
82
+ <div class="index-count">
83
+ <FaIcon @prefix="fas" @icon="store-alt" />
84
+ </div>
85
+ </div>
86
+ <div class="order-route-location dark:text-gray-100">
87
+ <DisplayPlace @place={{@options.order.payload.pickup}} @type="pickup" @addressClass="text-sm dark:text-gray-100" @noAddressClass="text-sm" />
88
+ </div>
89
+ </div>
90
+ <div class="order-route-stop">
91
+ <div class="order-route-stop-index">
92
+ <div class="index-count">
93
+ <FaIcon @prefix="fas" @icon="map-marker-alt" />
94
+ </div>
95
+ </div>
96
+ <div class="order-route-location dark:text-gray-100">
97
+ <DisplayPlace @place={{@options.order.payload.dropoff}} @type="dropoff" @addressClass="text-sm dark:text-gray-100" @noAddressClass="text-sm" />
98
+ </div>
99
+ </div>
100
+ </div>
101
+ {{/if}}
102
+ </div>
103
+ </div>
104
+ </div>
105
+ <div class="w-full my-2 flex flex-col">
106
+ <div class="flex px-6 py-4 border-t border-b border-gray-100 dark:border-gray-800">
107
+ <div class="flex-1 ">
108
+ <h5 class="dark:text-gray-100 font-semibold">Customer</h5>
109
+ </div>
110
+ </div>
111
+ <div class="py-2 px-6">
112
+ <div class="mb-4 mt-2 text-sm text-blue-900 dark:text-blue-50">
113
+ <div class="flex flex-row">
114
+ <div>
115
+ <img src={{avatar-url @options.order.customer.photo_url}} class="w-8 h-8 rounded-md shadow-sm mr-2" alt={{@options.order.customer.name}} />
116
+ </div>
117
+ <div>
118
+ <div class="font-bold">{{@options.order.customer.name}}</div>
119
+ <div>{{@options.order.customer.email}}</div>
120
+ <div>{{@options.order.customer.phone}}</div>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ {{#unless @options.order.meta.is_pickup}}
125
+ <div class="rounded-md bg-blue-50">
126
+ <div class="rounded-t-md bg-blue-100 px-3 py-2 mb-3">
127
+ <span class="text-blue-500 font-semibold text-sm truncate">Customer address</span>
128
+ </div>
129
+ <div class="flex flex-row items-center mb-4 pb-4 px-3">
130
+ <div class="flex items-center justify-center rounded-full bg-blue-500 w-8 h-8 mr-3">
131
+ <FaIcon @icon="map-marker-alt" class="text-white" />
132
+ </div>
133
+ <div class="text-xs text-blue-900 truncate">
134
+ <DisplayPlace @place={{@options.order.payload.dropoff}} @type="dropoff" />
135
+ </div>
136
+ </div>
137
+ </div>
138
+ {{/unless}}
139
+ </div>
140
+ </div>
141
+ <div class="w-full my-2 flex flex-col">
142
+ <div class="flex px-6 py-4 border-t border-b border-gray-100 dark:border-gray-800">
143
+ <div class="flex-1 flex-row justify-between items-center">
144
+ <h5 class="dark:text-gray-100 font-semibold">Tracking</h5>
145
+ <h5 class="dark:text-gray-100 font-semibold">({{@options.order.tracking}})</h5>
146
+ </div>
147
+ </div>
148
+ <div class="py-2 px-6">
149
+ <div class="flex flex-row items-center justify-center space-x-4">
150
+ <div class="p-2 rounded-md bg-white">
151
+ <img src={{concat "data:image/png;base64," @options.order.tracking_number.qr_code}} class="w-18 h-18" alt={{@options.order.public_id}} />
152
+ </div>
153
+ <div class="p-2 rounded-md bg-white">
154
+ <img src={{concat "data:image/png;base64," @options.order.tracking_number.barcode}} class="w-40 h-18" alt={{@options.order.public_id}} />
155
+ </div>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ <div class="w-full my-2">
160
+ <div class="flex items-center justify-between px-6 py-4 border-t border-b border-gray-100 dark:border-gray-800">
161
+ <div>
162
+ <h5 class="dark:text-gray-100 font-semibold">Order Summary</h5>
163
+ </div>
164
+ {{#if @options.order.payload.cod_amount}}
165
+ <div>
166
+ <FaIcon @icon="money-bill-wave" @size="sm" class="text-green-400 mr-1" />
167
+ <span class="font-semibold text-green-400 text-sm">Cash</span>
168
+ </div>
169
+ {{/if}}
170
+ </div>
171
+ <div class="flex flex-col space-y-4 p-6 overflow-hidden">
172
+ {{#each @options.order.payload.entities as |entity|}}
173
+ <div class="flex flex-1">
174
+ <div class="mr-2">
175
+ <div class="flex items-center justify-center w-5 h-5 border border-gray-100 dark:border-blue-400 rounded-md">
176
+ <span class="text-blue-400 text-xs">{{entity.meta.quantity}}x</span>
177
+ </div>
178
+ </div>
179
+ <div class="flex-1 flex">
180
+ <div class="mr-4">
181
+ <img src={{entity.photo_url}} class="w-12 h-12 rounded-md shadow-sm" alt={{entity.name}} />
182
+ </div>
183
+ <div>
184
+ <h4 class="font-semibold dark:text-gray-100 mb-1 text-sm">{{entity.name}}</h4>
185
+ <div class="flex flex-wrap truncate w-44">
186
+ <p class="dark:text-gray-50 text-xs truncate">{{entity.description}}</p>
187
+ </div>
188
+ <div>
189
+ {{#each entity.meta.variants as |variant|}}
190
+ <div>
191
+ <span class="text-xs dark:text-gray-50">{{variant.name}}</span>
192
+ </div>
193
+ {{/each}}
194
+ </div>
195
+ <div>
196
+ {{#each entity.meta.addons as |addon|}}
197
+ <div>
198
+ <span class="text-xs dark:text-gray-50">+ {{addon.name}}</span>
199
+ </div>
200
+ {{/each}}
201
+ </div>
202
+ </div>
203
+ </div>
204
+ <div>
205
+ <span class="dark:text-gray-50 text-sm">{{format-currency entity.meta.subtotal entity.currency}}</span>
206
+ </div>
207
+ </div>
208
+ {{/each}}
209
+ </div>
210
+ <div class="px-6 py-2.5 space-y-2 border-t border-b border-gray-100 dark:border-gray-800">
211
+ <div class="flex items-center justify-between">
212
+ <span class="dark:text-gray-50 text-sm">Subtotal</span>
213
+ <span class="dark:text-gray-50 text-sm">{{format-currency @options.order.meta.subtotal @options.order.meta.currency}}</span>
214
+ </div>
215
+ {{#unless @options.order.meta.is_pickup}}
216
+ <div class="flex items-center justify-between">
217
+ <span class="dark:text-gray-50 text-sm">Delivery fee</span>
218
+ <span class="dark:text-gray-50 text-sm">{{format-currency @options.order.meta.delivery_fee @options.order.meta.currency}}</span>
219
+ </div>
220
+ {{/unless}}
221
+ {{#if @options.order.meta.tip}}
222
+ <div class="flex items-center justify-between">
223
+ <span class="dark:text-gray-50 text-sm">Tip</span>
224
+ <span class="dark:text-gray-50 text-sm">{{get-tip-amount @options.order.meta.tip @options.order.meta.subtotal @options.order.meta.currency}}</span>
225
+ </div>
226
+ {{/if}}
227
+ {{#if @options.order.meta.delivery_tip}}
228
+ <div class="flex items-center justify-between">
229
+ <span class="dark:text-gray-50 text-sm">Delivery Tip</span>
230
+ <span class="dark:text-gray-50 text-sm">{{get-tip-amount @options.order.meta.delivery_tip @options.order.meta.subtotal @options.order.meta.currency}}</span>
231
+ </div>
232
+ {{/if}}
233
+ </div>
234
+ <div class="px-6 py-2">
235
+ <div class="flex items-center justify-between">
236
+ <span class="dark:text-gray-50 font-bold text-sm">Total</span>
237
+ <span class="dark:text-gray-50 font-bold text-sm">{{format-currency @options.order.meta.total @options.order.meta.currency}}</span>
238
+ </div>
239
+ </div>
240
+ </div>
241
+ </div>
242
+ </Modal::Default>
@@ -0,0 +1,50 @@
1
+ <Modal::Default @onOpen={{fn this.fetchCategories @options.store}} @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
2
+ <div class="modal-body-container">
3
+ <div class="flex items-center justify-between mb-4">
4
+ <div>
5
+ {{#if this.isLoading}}
6
+ <Spinner class="text-sky-400" />
7
+ {{/if}}
8
+ </div>
9
+ <div>
10
+ <Button @type="magic" @text="New Category" @icon="plus" @iconPrefix="fas" @onClick={{fn this.createCategory @options.store}} @disabled={{this.isLoading}} />
11
+ </div>
12
+ </div>
13
+
14
+ <div class="space-y-4">
15
+ {{#each this.categories as |category index|}}
16
+ <div>
17
+ <div class="flex items-center rounded-md shadow-sm px-3 py-2 font-semibold bg-gray-200 dark:bg-gray-800 dark:text-gray-100 mb-2">
18
+ <div class="flex-1 flex items-center">
19
+ <FaIcon @icon="pencil" class="mr-1 dark:text-gray-100" />
20
+ <Input @type="text" @value={{category.name}} {{on "blur" (fn this.saveCategory category)}} class="w-full px-2 m-0 border-none bg-transparent dark:text-gray-100" />
21
+ </div>
22
+ <div class="flex items-center">
23
+ <Button @text="New Addon" @icon="plus" @iconPrefix="fas" @onClick={{fn this.insertNewAddon category}} class="mr-3" />
24
+ <a href="javascript:;" {{on "click" (fn this.deleteCategory index)}} class="destroy-action opacity-50 hover:opacity-100 text-sm">Delete Category</a>
25
+ </div>
26
+ </div>
27
+ <div class="space-y-2 mb-2">
28
+ {{#each category.addons as |addon i|}}
29
+ <div class="grid grid-cols-10 gap-1 px-3 py-2 rounded-md dark:bg-gray-900 bg-gray-200">
30
+ <div class="col-span-3 flex items-center">
31
+ <FaIcon @icon="tag" class="text-sky-400 mr-2" />
32
+ <Input @type="text" @value={{addon.name}} {{on "blur" (fn this.saveAddon addon)}} class="form-input flex-1 w-full" placeholder="Addon Name" />
33
+ </div>
34
+ <div class="col-span-4">
35
+ <Input @type="text" @value={{addon.description}} {{on "blur" (fn this.saveAddon addon)}} class="form-input w-full" placeholder="Addon Description" />
36
+ </div>
37
+ <div class="col-span-2">
38
+ <MoneyInput class="w-full" @currency={{this.activeStore.currency}} @canSelectCurrency={{false}} @value={{addon.price}} @onFormatCompleted={{fn this.saveAddon addon}} @disabled={{this.isLoading}} />
39
+ </div>
40
+ <div class="flex items-center justify-center text-center text-sm">
41
+ <a href="javascript:;" class="destroy-action opacity-50 hover:opacity-100" {{on "click" (fn this.removeAddon category i)}}>Remove</a>
42
+ </div>
43
+ </div>
44
+ {{/each}}
45
+ </div>
46
+ </div>
47
+ {{/each}}
48
+ </div>
49
+ </div>
50
+ </Modal::Default>
@@ -0,0 +1,86 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { action } from '@ember/object';
5
+ import { alias } from '@ember/object/computed';
6
+
7
+ export default class ModalsManageAddonsComponent extends Component {
8
+ @service store;
9
+ @service currentUser;
10
+ @service modalsManager;
11
+ @tracked categories = [];
12
+ @tracked isLoading = true;
13
+
14
+ @action saveAddon(addon) {
15
+ this.isLoading = true;
16
+
17
+ return addon.save().then(() => {
18
+ this.isLoading = false;
19
+ });
20
+ }
21
+
22
+ @action insertNewAddon(category) {
23
+ const productAddon = this.store.createRecord('product-addon', { category_uuid: category.id });
24
+ category.addons.pushObject(productAddon);
25
+ }
26
+
27
+ @action removeAddon(category, index) {
28
+ const addon = category.addons.objectAt(index);
29
+
30
+ category.addons.removeAt(index);
31
+ return addon.destroyRecord();
32
+ }
33
+
34
+ @action saveCategory(category) {
35
+ this.isLoading = true;
36
+ return category.save().then(() => {
37
+ this.isLoading = false;
38
+ });
39
+ }
40
+
41
+ @action deleteCategory(index) {
42
+ const category = this.categories.objectAt(index);
43
+ const result = confirm('Are you sure you wish to delete this addon category? All addons assosciated will be lost!');
44
+
45
+ if (result) {
46
+ this.categories.removeAt(index);
47
+ return category.destroyRecord();
48
+ }
49
+ }
50
+
51
+ @action pushCategory(category) {
52
+ const { categories } = this;
53
+ categories.pushObject(category);
54
+ }
55
+
56
+ @action createCategory(store) {
57
+ const category = this.store.createRecord('addon-category', {
58
+ name: 'Untitled Addon Category',
59
+ for: 'storefront_product_addon',
60
+ owner_type: 'storefront:store',
61
+ owner_uuid: store.id,
62
+ });
63
+
64
+ this.isLoading = true;
65
+
66
+ return category.save().then((category) => {
67
+ this.pushCategory(category);
68
+ this.isLoading = false;
69
+ });
70
+ }
71
+
72
+ @action fetchCategories(store) {
73
+ this.isLoading = true;
74
+
75
+ return this.store
76
+ .query('addon-category', {
77
+ owner_uuid: store.id,
78
+ })
79
+ .then((categories) => {
80
+ this.categories = categories.toArray();
81
+ })
82
+ .finally(() => {
83
+ this.isLoading = false;
84
+ });
85
+ }
86
+ }
@@ -0,0 +1,36 @@
1
+ <Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
2
+ <div class="modal-body-container">
3
+ <div class="sm:flex sm:items-start">
4
+ <div
5
+ class="flex items-center justify-center flex-shrink-0 w-12 h-12 mx-auto bg-red-100 rounded-full sm:mx-0 sm:h-10 sm:w-10">
6
+ <svg class="w-6 h-6 text-red-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
7
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
8
+ d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z">
9
+ </path>
10
+ </svg>
11
+ </div>
12
+ <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
13
+ <div class="mb-4">
14
+ <p class="text-sm leading-5 text-gray-500 dark:text-white">
15
+ You are about to set this order as ready and dispatch, use the dropdown below to select a driver
16
+ to dispatch to. <br><br>Or optionally you can opt to dispatch order as adhoc which will ping the
17
+ order to all nearby drivers to be accepted.
18
+ </p>
19
+ </div>
20
+ <div class="input-group">
21
+ <ShortToggle @isToggled={{@options.adhoc}} @onToggle={{fn (mut @options.adhoc)}} @label="Adhoc dispatch to nearby drivers" />
22
+ </div>
23
+ {{#unless @options.adhoc}}
24
+ <InputGroup class="mt-4" @name="Select Driver">
25
+ <ModelSelect @modelName="driver" @selectedModel={{@options.driver}}
26
+ @placeholder="Select Driver to Assign" @triggerClass="form-select form-input"
27
+ @infiniteScroll={{false}} @renderInPlace={{true}} @onChange={{fn (mut
28
+ @options.driver)}} as |model|>
29
+ {{model.name}}
30
+ </ModelSelect>
31
+ </InputGroup>
32
+ {{/unless}}
33
+ </div>
34
+ </div>
35
+ </div>
36
+ </Modal::Default>
@@ -0,0 +1,5 @@
1
+ <Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
2
+ <div class="modal-body-container">
3
+ <ComboBox @options={{@options.addonCategories}} @selected={{@options.product.addon_categories}} @optionLabel="name" @comparator="name" @selectionBoxLabel="Selected" @onChange={{@options.updateProductAddonCategories}} />
4
+ </div>
5
+ </Modal::Default>
@@ -0,0 +1,35 @@
1
+ <Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
2
+ <div class="modal-body-container">
3
+ <div class="flex flex-col items-center justify-center mb-2">
4
+ <FaIcon @icon="mail-bulk" @size="4x" class="text-sky-400" />
5
+ <div class="my-2 text-center">
6
+ <h2 class="dark:text-gray-100 font-semibold">Invite members to your network</h2>
7
+ <p class="my-2 px-6">
8
+ Grab a shareable invitiation link or send individual invites via email below.
9
+ </p>
10
+ </div>
11
+ </div>
12
+
13
+ <div class="rounded-md border dark:border-gray-800 dark:bg-gray-800 p-4 mb-5">
14
+ <h4 class="dark:text-gray-50 font-semibold mb-2">Share with people and organizations</h4>
15
+ <p class="mb-4 text-sm dark:text-gray-200">
16
+ Enter the emails of people or organizations you want to send an invite to your network.
17
+ </p>
18
+ <div>
19
+ <TagInput class="form-input" @placeholder="Add emails" @tags={{@options.recipients}} @addTag={{@options.addRecipient}} @removeTagAtIndex={{@options.removeRecipient}} as |tag|>
20
+ {{tag}}
21
+ </TagInput>
22
+ </div>
23
+ </div>
24
+
25
+ <div class="rounded-md border dark:border-gray-800 dark:bg-gray-800 p-4">
26
+ <h4 class="dark:text-gray-50 mb-4 font-semibold">Get link</h4>
27
+ <div class="input-group mb-0">
28
+ <ShortToggle @isToggled={{@options.network.options.shareable_link_enabled}} @onToggle={{@options.toggleShareableLink}} @label="Enable shareable link" @helpText="Anyone with this link is able to join your network" />
29
+ </div>
30
+ {{#if @options.network.options.shareable_link_enabled}}
31
+ <ClickToCopy class="mt-4 rounded-md border dark:border-gray-900 dark:bg-gray-900 truncate p-4 text-sm text-green-400 dark:text-green-300 text-center" @value={{@options.shareableLink}} />
32
+ {{/if}}
33
+ </div>
34
+ </div>
35
+ </Modal::Default>
@@ -0,0 +1,30 @@
1
+ <Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
2
+ <div class="modal-body-container">
3
+ <div class="grid grid-cols-3 gap-1 text-xs dark:text-gray-100">
4
+ <InputGroup @name="Name" @autocomplete="nope" @value={{@options.place.name}} @wrapperClass="col-span-3" />
5
+ <InputGroup @name="Street 1" @value={{@options.place.street1}} @wrapperClass="col-span-3">
6
+ <AutocompleteInput @value={{@options.place.street1}} @onSelect={{@options.autocomplete}} placeholder="Street 1" class="w-full" as |result|>
7
+ {{result.address}}
8
+ </AutocompleteInput>
9
+ </InputGroup>
10
+ <InputGroup @name="Street 2" @autocomplete="nope" @value={{@options.place.street2}} @wrapperClass="col-span-3" />
11
+ <InputGroup @name="Neighborhood" @autocomplete="nope" @value={{@options.place.neighborhood}} />
12
+ <InputGroup @name="Building" @autocomplete="nope" @value={{@options.place.building}} />
13
+ <InputGroup @name="Security Access Code" @autocomplete="nope" @value={{@options.place.security_access_code}} />
14
+ <InputGroup @name="Postal Code" @autocomplete="nope" @value={{@options.place.postal_code}} />
15
+ <InputGroup @name="City" @autocomplete="nope" @value={{@options.place.city}} />
16
+ <InputGroup @name="State" @autocomplete="nope" @value={{@options.place.province}} />
17
+ <InputGroup @name="Country" @wrapperClass="col-span-2">
18
+ <CountrySelect class="w-full form-input form-select form-datalist" @value={{@options.place.country}} @onChange={{fn (mut @options.place.country)}} placeholder="Country" />
19
+ </InputGroup>
20
+ <InputGroup @name="Coordinates" @wrapperClass="col-span-2">
21
+ <CoordinatesInput @value={{@options.place.location}} @onChange={{@options.updatePlaceCoordinates}} @onGeocode={{@options.autocomplete}} @onInit={{@options.setCoordinatesInput}} />
22
+ </InputGroup>
23
+ <div class="col-span-1"></div>
24
+ <InputGroup @name="Phone">
25
+ <PhoneInput @value={{@options.place.phone}} @autocomplete="nope" @onInput={{fn (mut @options.place.phone)}} class="form-input w-full" />
26
+ </InputGroup>
27
+ <InputGroup @name="Email" @autocomplete="nope" @value={{@options.place.email}} />
28
+ </div>
29
+ </div>
30
+ </Modal::Default>
@@ -0,0 +1 @@
1
+ {{yield}}
@@ -0,0 +1,3 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class OrderCardComponent extends Component {}
@@ -0,0 +1,22 @@
1
+ <div class="schedule-manager-wrapper" ...attributes>
2
+ {{#each-in this.schedule as |day hours|}}
3
+ <div class="content-panel {{@contentPanelClass}} shadow-sm">
4
+ <div class="content-panel-header items-center {{@contentPanelHeaderClass}}">
5
+ <h4 class="font-semibold dark:text-gray-100">{{day}}</h4>
6
+ <div>
7
+ <Button @icon="calendar-week" @text="Add Hours" @onClick={{fn this.addHours @subject day}} class="{{@addHoursButtonClass}}" />
8
+ </div>
9
+ </div>
10
+ <div class="content-panel-body {{@contentPanelBodyClass}}">
11
+ {{#each hours as |hour|}}
12
+ <div class="flex items-center justify-between mb-2">
13
+ <div class="dark:text-gray-100">{{hour.humanReadableHours}}</div>
14
+ <div>
15
+ <Button @iconPrefix="fas" @type="danger" @size="xs" @icon="times" @onClick={{fn this.removeHours hour}} class="{{@removeHoursButtonClass}}" />
16
+ </div>
17
+ </div>
18
+ {{/each}}
19
+ </div>
20
+ </div>
21
+ {{/each-in}}
22
+ </div>
@@ -0,0 +1,73 @@
1
+ import Component from '@glimmer/component';
2
+ import { inject as service } from '@ember/service';
3
+ import { action, computed } from '@ember/object';
4
+
5
+ export default class ScheduleManagerComponent extends Component {
6
+ @service notifications;
7
+ @service modalsManager;
8
+ @service store;
9
+
10
+ @computed('args.subject.hours.@each.id', 'hours.length') get schedule() {
11
+ const schedule = {};
12
+ const week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
13
+ const { subject } = this.args;
14
+ const { hours } = subject;
15
+
16
+ for (let i = 0; i < week.length; i++) {
17
+ const day = week.objectAt(i);
18
+
19
+ schedule[day] = [];
20
+ }
21
+
22
+ for (let i = 0; i < hours.length; i++) {
23
+ const hour = hours.objectAt(i);
24
+
25
+ schedule[hour.day_of_week].pushObject(hour);
26
+ }
27
+
28
+ return schedule;
29
+ }
30
+
31
+ @computed('args.hourModelType') get hourModelType() {
32
+ const { hourModelType } = this.args;
33
+
34
+ return hourModelType ?? 'store-hour';
35
+ }
36
+
37
+ @action addHours(subject, day) {
38
+ const { subjectKey } = this.args;
39
+
40
+ const hours = this.store.createRecord(this.hourModelType, {
41
+ [subjectKey]: subject.id,
42
+ day_of_week: day,
43
+ });
44
+
45
+ this.modalsManager.show('modals/add-store-hours', {
46
+ title: `Add new hours for ${day}`,
47
+ acceptButtonText: 'Add hours',
48
+ acceptButtonIcon: 'save',
49
+ hours,
50
+ confirm: (modal) => {
51
+ modal.startLoading();
52
+
53
+ return hours.save().then((hours) => {
54
+ subject.hours.pushObject(hours);
55
+ this.notifications.success(`New hours added for ${day}`);
56
+ });
57
+ },
58
+ });
59
+ }
60
+
61
+ @action removeHours(hours) {
62
+ this.modalsManager.confirm({
63
+ title: 'Are you sure you wish to remove these hours?',
64
+ body: 'By removing these operation/availability hours, your store or product may become inactive or unavailable according to the updated schedule...',
65
+ acceptButtonIcon: 'trash',
66
+ confirm: (modal) => {
67
+ modal.startLoading();
68
+
69
+ return hours.destroyRecord();
70
+ },
71
+ });
72
+ }
73
+ }
@@ -0,0 +1,7 @@
1
+ <div class="overflow-y-scroll h-screen">
2
+ <div class="h-screen" {{increase-height-by 2000}}>
3
+ <main class="h-screen max-w-xl mx-auto pt-10 pb-12 lg:pb-16" ...attributes>
4
+ {{yield}}
5
+ </main>
6
+ </div>
7
+ </div>
@@ -0,0 +1,21 @@
1
+ {{#if @activeStore}}
2
+ <DropdownButton @renderInPlace={{true}} @size="xs" @type="primary" @icon="store" @iconSize="sm" @text={{@activeStore.name}} @buttonClass={{concat "w-full " @buttonClass}} @buttonWrapperClass={{concat "w-full " @buttonWrapperClass}} @wrapperClass={{@wrapperClass}} as |dd|>
3
+ <div class="next-dd-menu py-1">
4
+ <div class="px-1 overflow-y-scroll" {{set-height "300px"}}>
5
+ {{#each @stores as |store|}}
6
+ <a href="javascript:;" class="next-dd-item" role="menuitem" {{on "click" (dropdown-fn dd this.onSwitchStore store)}}>
7
+ {{or store.name "-"}}
8
+ </a>
9
+ {{/each}}
10
+ </div>
11
+ <div class="px-1">
12
+ <div class="next-dd-menu-seperator"></div>
13
+ <div class="px-1">
14
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.onCreateStore)}}>
15
+ Create a new storefront
16
+ </a>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </DropdownButton>
21
+ {{/if}}