Commands.svelte 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <script>
  2. import { onMount } from 'svelte';
  3. import { goto } from '$app/navigation';
  4. import { browser } from '$app/environment';
  5. const save_icon = '/assets/save_icon.svg';
  6. const arrow_back = '/assets/arrow_back.svg';
  7. let token = null;
  8. let companyId = null;
  9. let userId = null;
  10. let tableId = null;
  11. let flag = null;
  12. let orderToCancel = null;
  13. const API = (import.meta.env.VITE_API_URL || '').replace(/\/+$/, '');
  14. if (browser) {
  15. token = localStorage.getItem('token');
  16. companyId = Number(localStorage.getItem('company'));
  17. userId = localStorage.getItem('user');
  18. tableId = Number(localStorage.getItem('table'));
  19. flag = localStorage.getItem('flag');
  20. localStorage.setItem('typePage', 'false');
  21. }
  22. let orders = [];
  23. let isCreatingOrder = false;
  24. let customerName = '';
  25. let customerPhone = '';
  26. let showConfirmCancel = false;
  27. const fetchOrders = async () => {
  28. if (!companyId || !tableId) return;
  29. try {
  30. const response = await fetch(`${API}/order/get`, {
  31. method: 'POST',
  32. headers: {
  33. 'Content-Type': 'application/json',
  34. Authorization: `Bearer ${token}`
  35. },
  36. body: JSON.stringify({ company_id: companyId, table_id: tableId })
  37. });
  38. const result = await response.json();
  39. if (result.status === 'ok') {
  40. orders = result.data.map((o) => ({
  41. id: o.order_id,
  42. name: o.order_name,
  43. phone: o.order_phone,
  44. createdAt: o.order_created_at,
  45. status: o.status_status
  46. }));
  47. } else {
  48. console.error('Failed to fetch orders:', result.msg);
  49. }
  50. } catch (err) {
  51. console.error('Request error:', err);
  52. }
  53. };
  54. const openOrder = (orderId) => {
  55. goto(`/pos/${orderId}`);
  56. };
  57. const createOrder = async () => {
  58. if (!customerName.trim()) return;
  59. try {
  60. const response = await fetch(`${API}/order/create`, {
  61. method: 'POST',
  62. headers: {
  63. 'Content-Type': 'application/json',
  64. Authorization: `Bearer ${token}`
  65. },
  66. body: JSON.stringify({
  67. table_id: tableId,
  68. user_name: userId,
  69. company_id: companyId,
  70. order_name: customerName,
  71. order_phone: customerPhone || '',
  72. status_status: 'Aberta'
  73. })
  74. });
  75. const result = await response.json();
  76. if (result.status === 'ok') {
  77. isCreatingOrder = false;
  78. customerName = '';
  79. customerPhone = '';
  80. await fetchOrders();
  81. } else {
  82. console.error('Failed to create order:', result.msg);
  83. }
  84. } catch (err) {
  85. console.error('Error creating order:', err);
  86. }
  87. };
  88. function cancelCommand(order_Id) {
  89. const myHeaders = new Headers();
  90. myHeaders.append('Authorization', `Bearer ${token}`);
  91. myHeaders.append('Content-Type', 'application/json');
  92. const raw = JSON.stringify({
  93. order_id: order_Id,
  94. company_id: companyId,
  95. cancel: true
  96. });
  97. const requestOptions = {
  98. method: 'POST',
  99. headers: myHeaders,
  100. body: raw,
  101. redirect: 'follow'
  102. };
  103. fetch(`${API}/order/delete`, requestOptions)
  104. .then((response) => response.json())
  105. .then((result) => {
  106. if (result.status === 'ok') {
  107. // Remove the canceled order from the local orders array
  108. orders = orders.filter(order => order.id !== order_Id);
  109. console.log('Pedido cancelado com sucesso:', order_Id);
  110. } else {
  111. console.error('Erro ao cancelar comanda:', result.msg);
  112. }
  113. })
  114. .catch((error) => console.error('Erro ao cancelar comanda:', error));
  115. }
  116. const getElapsedTime = (createdAt) => {
  117. if (!createdAt || createdAt.trim() === '') return '';
  118. const start = new Date(createdAt.replace(' ', 'T'));
  119. const now = new Date();
  120. const diff = Math.floor((now - start) / 60000); // in minutes
  121. if (diff < 60) return `${diff} min`;
  122. const hours = Math.floor(diff / 60);
  123. const minutes = diff % 60;
  124. return `${hours}h ${minutes}m`;
  125. };
  126. function handleAddProduct(order_id) {
  127. localStorage.setItem('order', order_id);
  128. goto('/dashboard/addproducts');
  129. }
  130. function handleEndProduct(order_id) {
  131. localStorage.setItem('order', order_id);
  132. goto('/dashboard/endcommand');
  133. }
  134. onMount(() => {
  135. fetchOrders();
  136. setInterval(() => {
  137. fetchOrders();
  138. }, 5000);
  139. });
  140. </script>
  141. <div class="mb-6 flex w-full items-center">
  142. <button
  143. on:click={() => goto('/dashboard/tables')}
  144. class="mr-4 rounded-lg bg-gray-800 p-2 hover:bg-gray-700"
  145. >
  146. <img src={arrow_back} alt="Voltar" class="h-5 w-5" />
  147. </button>
  148. </div>
  149. <div class="container mx-auto w-full rounded-md bg-gray-800 p-4">
  150. <h1 class="mb-6 text-center text-2xl font-bold">Comandas</h1>
  151. <div
  152. class="grid grid-cols-2 justify-items-center gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5"
  153. >
  154. {#each orders as order}
  155. <div
  156. class="w-full max-w-xs rounded-lg bg-gray-900 shadow-md transition-transform hover:scale-105"
  157. >
  158. <div class="flex flex-col items-center justify-between rounded-t-lg bg-emerald-700 p-4">
  159. <span class="font-medium">{order.name}</span>
  160. <span class="font-medium">{order.phone}</span>
  161. </div>
  162. <div class="p-4">
  163. <div class="mb-2 text-sm text-gray-400">
  164. {getElapsedTime(order.createdAt)}
  165. </div>
  166. <!--adicionar aqui link para o addproduct preciso salvar uma variavel com o order_id e etc para aparecer apenas o item da comanda em especifico-->
  167. <button
  168. class="mb-2 w-full rounded bg-emerald-600 py-2 hover:bg-emerald-700"
  169. on:click={handleAddProduct(order.id)}
  170. >
  171. Adicionar items
  172. </button>
  173. {#if flag == 'cashier' || flag == 'admin'}
  174. <button
  175. class="mb-2 w-full rounded bg-yellow-600 py-2 hover:bg-yellow-700"
  176. on:click={handleEndProduct(order.id)}
  177. >
  178. Finalizar Comanda
  179. </button>
  180. {/if}
  181. {#if flag == 'admin'}
  182. <button
  183. class="w-full rounded bg-red-600 py-2 hover:bg-red-700"
  184. on:click={cancelCommand(order.id)}
  185. >
  186. Cancelar
  187. </button>
  188. {/if}
  189. </div>
  190. </div>
  191. {/each}
  192. </div>
  193. <div class="mt-6 flex justify-center">
  194. <button
  195. class="rounded-md bg-green-600 px-4 py-2 text-white hover:bg-green-700"
  196. on:click={() => (isCreatingOrder = true)}
  197. >
  198. Adicionar Comanda
  199. </button>
  200. </div>
  201. </div>
  202. {#if isCreatingOrder}
  203. <div class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
  204. <div class="w-full max-w-md rounded-lg bg-gray-800 p-6 shadow-lg">
  205. <h2 class="mb-4 text-lg font-semibold">New Order</h2>
  206. <form on:submit|preventDefault={createOrder} class="space-y-4">
  207. <div>
  208. <p class="mb-1 block text-sm text-gray-400">Nome</p>
  209. <input
  210. bind:value={customerName}
  211. placeholder="Ex: John Doe"
  212. class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
  213. />
  214. </div>
  215. <div>
  216. <p class="mb-1 block text-sm text-gray-400">Numero (optional)</p>
  217. <input
  218. bind:value={customerPhone}
  219. placeholder="(11) 99999-9999"
  220. class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
  221. />
  222. </div>
  223. <div class="flex justify-end space-x-2">
  224. <button
  225. type="button"
  226. on:click={() => (isCreatingOrder = false)}
  227. class="rounded-lg bg-gray-700 px-4 py-2 hover:bg-gray-600"
  228. >
  229. Cancelar
  230. </button>
  231. <button
  232. type="submit"
  233. class="flex items-center rounded-lg bg-emerald-600 px-4 py-2 hover:bg-emerald-700"
  234. >
  235. <img src={save_icon} alt="Save" class="mr-2 h-4 w-4" /> Salvar
  236. </button>
  237. </div>
  238. </form>
  239. </div>
  240. </div>
  241. {/if}
  242. {#if showConfirmCancel}
  243. <div class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
  244. <div class="w-full max-w-sm rounded-lg bg-gray-800 p-6">
  245. <h2 class="mb-4 text-lg font-bold">Confirmar Exclusão</h2>
  246. <p class="mb-4">Deseja realmente cancelar a comanda {orderToCancel}?</p>
  247. <div class="flex justify-end gap-2">
  248. <button
  249. on:click={() => (showConfirmCancel = false)}
  250. class="rounded bg-gray-600 px-4 py-2 text-white transition-colors hover:bg-gray-700"
  251. >
  252. Cancelar
  253. </button>
  254. <button
  255. on:click={deleteTable}
  256. class="rounded bg-red-600 px-4 py-2 text-white transition-colors hover:bg-red-700"
  257. >
  258. Excluir
  259. </button>
  260. </div>
  261. </div>
  262. </div>
  263. {/if}