Jelajahi Sumber

add the command page (adicionar logica no cancelar e adicionar logica no adicionar items)

gdias 4 bulan lalu
induk
melakukan
fba6ba8f55

+ 123 - 247
src/lib/component/Commands.svelte

@@ -1,308 +1,184 @@
 <script>
-	import { goto } from '$app/navigation';
 	import { onMount } from 'svelte';
+	import { goto } from '$app/navigation';
 	import { browser } from '$app/environment';
-	import add_icon from '$lib/assets/add_icon.svg';
 	import save_icon from '$lib/assets/save_icon.svg';
-	import trash_icon from '$lib/assets/trash_icon.svg';
 
 	let token = null;
-	let company = null;
+	let companyId = null;
+	let userId = null;
+	let tableId = null;
 	let flag = null;
 
 	if (browser) {
 		token = localStorage.getItem('token');
-		company = Number(localStorage.getItem('company'));
+		companyId = Number(localStorage.getItem('company'));
+		userId = localStorage.getItem('user');
+		tableId = Number(localStorage.getItem('table'));
 		flag = localStorage.getItem('flag');
 	}
 
-	const statusMap = {
-		1: 'FREE',
-		2: 'OCCUPIED',
-		3: 'ALERT'
-	};
-
-	const statusToApiMap = {
-		FREE: 'Livre',
-		OCCUPIED: 'Ocupado',
-		ALERT: 'Alerta'
-	};
-
-	let tables = [];
-
-	let orders = {};
-
-	let newTableNumber = '';
-	let tableToDelete = null;
-	let isAddingCommand = false;
-
-	const getTableOrder = (tableId) => {
-		return orders[tableId];
-	};
-
-	const updateTableStatus = async (tableNumber, newStatus) => {
-		const requestOptions = {
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json',
-				Authorization: `Bearer ${token}`
-			},
-			redirect: 'follow',
-			body: JSON.stringify({
-				table_number: tableNumber,
-				company_id: company,
-				status_status: statusToApiMap[newStatus]
-			})
-		};
-
-		const response = await fetch('https://dev2.mixtech.dev.br/table/update', requestOptions);
-		const result = await response.json();
-		if (result.status !== 'ok') {
-			throw new Error('Falha ao atualizar status: ' + result.msg);
-		}
-	};
-
-	const startOrder = async (tableId, tableNumber) => {
-		await updateTableStatus(tableNumber, 'OCCUPIED');
-		tables = tables.map((t) => {
-			if (t.id === tableId) {
-				return { ...t, status: 'OCCUPIED', startTime: new Date().toISOString() };
-			}
-			return t;
-		});
-		orders = { ...orders, [tableId]: { items: [], totalAmount: 0 } };
-		console.log(`Order started for table ${tableId}`);
-	};
-
-	const getStatusColor = (status) => {
-		switch (status) {
-			case 'FREE':
-				return 'bg-green-600 hover:bg-green-700';
-			case 'OCCUPIED':
-				return 'bg-yellow-500 hover:bg-yellow-600';
-			case 'ALERT':
-				return 'bg-red-600 hover:bg-red-700';
-			default:
-				return 'bg-gray-700 hover:bg-gray-800';
-		}
-	};
-
-	const getStatusText = (status) => {
-		switch (status) {
-			case 'FREE':
-				return 'Livre';
-			case 'OCCUPIED':
-				return 'Ocupada';
-			case 'ALERT':
-				return 'Alerta';
-			default:
-				return 'Desconhecido';
-		}
-	};
-
-	const getOrderTime = (startTime) => {
-		if (!startTime) return '';
-
-		const startDateTime = new Date(startTime);
-		const now = new Date();
-		const diff = Math.floor((now.getTime() - startDateTime.getTime()) / 1000 / 60);
-
-		if (diff < 60) {
-			return `${diff} min`;
-		} else {
-			const hours = Math.floor(diff / 60);
-			const mins = diff % 60;
-			return `${hours}h ${mins}m`;
-		}
-	};
-
-	const handleTableClick = async (tableId, tableNumber) => {
-		const table = tables.find((t) => t.id === tableId);
-		if (!table) return;
-
-		if (table.status === 'FREE') {
-			await startOrder(tableId, tableNumber);
-		} else {
-			await goto(`/pos/${tableId}`);
-		}
-	};
-
-	const openDeleteConfirm = (tableId, tableNumber) => {
-		tableToDelete = { id: tableId, number: tableNumber };
-		showConfirmDelete = true;
-	};
-
-	const resetCommandForm = async () => {
-		isAddingCommand = false;
-	};
-	const deleteTable = async () => {
-		if (!tableToDelete) return;
-
-		const requestOptions = {
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json',
-				Authorization: `Bearer ${token}`
-			},
-			redirect: 'follow',
-			body: JSON.stringify({
-				table_number: tableToDelete.number,
-				company_id: company
-			})
-		};
+	let orders = [];
+	let isCreatingOrder = false;
+	let customerName = '';
+	let customerPhone = '';
 
+	const fetchOrders = async () => {
+		if (!companyId || !tableId) return;
 		try {
-			const response = await fetch('https://dev2.mixtech.dev.br/table/delete', requestOptions);
+			const response = await fetch('https://dev2.mixtech.dev.br/order/get', {
+				method: 'POST',
+				headers: {
+					'Content-Type': 'application/json',
+					Authorization: `Bearer ${token}`
+				},
+				body: JSON.stringify({ company_id: companyId, table_id: tableId })
+			});
 			const result = await response.json();
+
 			if (result.status === 'ok') {
-				tables = tables.filter((t) => t.id !== tableToDelete.id);
-				const newOrders = { ...orders };
-				delete newOrders[tableToDelete.id];
-				orders = newOrders;
-				showConfirmDelete = false;
-				tableToDelete = null;
+				orders = result.data.map((o) => ({
+					id: o.order_id,
+					name: o.order_name,
+					phone: o.order_phone,
+					createdAt: o.order_created_at,
+					status: o.status_status
+				}));
 			} else {
-				console.error('Erro ao excluir mesa:', result.msg);
+				console.error('Failed to fetch orders:', result.msg);
 			}
-		} catch (error) {
-			console.error(error);
+		} catch (err) {
+			console.error('Request error:', err);
 		}
 	};
 
-	const fetchTables = async () => {
-		const requestOptions = {
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json',
-				Authorization: `Bearer ${token}`
-			},
-			redirect: 'follow',
-			body: JSON.stringify({ company_id: company })
-		};
+	const openOrder = (orderId) => {
+		goto(`/pos/${orderId}`);
+	};
 
+	const createOrder = async () => {
+		if (!customerName.trim()) return;
+		console.log(userId);
 		try {
-			const response = await fetch('https://dev2.mixtech.dev.br/table/get', requestOptions);
+			const response = await fetch('https://dev2.mixtech.dev.br/order/create', {
+				method: 'POST',
+				headers: {
+					'Content-Type': 'application/json',
+					Authorization: `Bearer ${token}`
+				},
+				body: JSON.stringify({
+					table_id: tableId,
+					user_name: userId,
+					company_id: companyId,
+					order_name: customerName,
+					order_phone: customerPhone || ''
+				})
+			});
 			const result = await response.json();
 			if (result.status === 'ok') {
-				tables = result.data.map((d) => ({
-					id: d.table_id,
-					number: d.table_number,
-					status: statusMap[d.status_id] || 'Desconhecido',
-					startTime: statusMap[d.status_id] === 'FREE' ? null : new Date().toISOString()
-				}));
-				tables.forEach((t) => {
-					if (t.status !== 'FREE' && !orders[t.id]) {
-						orders[t.id] = { items: [], totalAmount: 0 };
-					}
-				});
-				orders = { ...orders };
+				isCreatingOrder = false;
+				customerName = '';
+				customerPhone = '';
+				await fetchOrders();
 			} else {
-				console.error('Erro ao buscar mesas:', result.msg);
+				console.error('Failed to create order:', result.msg);
 			}
-		} catch (error) {
-			console.error(error);
+		} catch (err) {
+			console.error('Error creating order:', err);
 		}
 	};
 
-	const createCommand = async () => {
-		isAddingCommand = true;
+	const getElapsedTime = (createdAt) => {
+		if (!createdAt || createdAt.trim() === '') return '';
+		const start = new Date(createdAt.replace(' ', 'T'));
+		const now = new Date();
+		const diff = Math.floor((now - start) / 60000); // in minutes
+
+		if (diff < 60) return `${diff} min`;
+		const hours = Math.floor(diff / 60);
+		const minutes = diff % 60;
+		return `${hours}h ${minutes}m`;
 	};
 
 	onMount(() => {
-		fetchTables();
+		fetchOrders();
+		setInterval(() => {
+			fetchOrders();
+			console.log('atualizou');
+		}, 5000);
 	});
 </script>
 
-<div class="container mx-auto h-full w-full rounded-md bg-gray-700">
-	<div class="flex flex-col">
-		<h1 class="mb-6 text-center text-2xl font-bold">Comandas</h1>
-		<div class="mx-auto max-w-7xl px-4">
+<div class="container mx-auto w-full rounded-md bg-gray-800 p-4">
+	<h1 class="mb-6 text-center text-2xl font-bold">Comandas</h1>
+
+	<div
+		class="grid grid-cols-2 justify-items-center gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5"
+	>
+		{#each orders as order}
 			<div
-				class="grid grid-cols-2 justify-items-center gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5"
+				class="w-full max-w-xs rounded-lg bg-gray-900 shadow-md transition-transform hover:scale-105"
 			>
-				{#each tables as table}
-					{@const order = getTableOrder(table.id)}
-
-					<div
-						class="w-full max-w-xs transform overflow-hidden rounded-lg bg-gray-800 shadow-md transition-transform duration-200 hover:scale-105"
-					>
-						<div class={`flex items-center justify-between p-4 ${getStatusColor(table.status)}`}>
-							<span class="font-medium">Mesa {table.number}</span>
-							<span class="text-sm font-medium">{getStatusText(table.status)}</span>
-						</div>
-
-						<div class="p-4">
-							<div class="flex flex-col items-center justify-center space-y-2 py-4">
-								<div class="space-y-3">
-									<div class="flex justify-between text-sm">
-										<span class="text-gray-400">{getOrderTime(table.startTime)}</span>
-										<!-- <div class="font-medium">
-											{order.items.length}
-											{order.items.length === 1 ? 'item' : 'itens'}
-										</div> -->
-									</div>
-
-									<div class="flex justify-between text-sm">
-										<span class="text-gray-400">Total:</span>
-										<!-- <span class="font-medium">
-											R$ {order.totalAmount.toFixed(2)}
-										</span> -->
-									</div>
-								</div>
-								<button
-									on:click={() => handleTableClick(table.id, table.number)}
-									class="flex items-center justify-center rounded bg-emerald-600 px-4 py-2 transition-colors hover:bg-emerald-700"
-								>
-									Comanda
-								</button>
-								<div>
-									<button
-										on:click={() => openDeleteConfirm(table.id, table.number)}
-										class="flex items-center justify-center rounded bg-red-600 px-4 py-2 text-sm transition-colors hover:bg-red-700"
-									>
-										Cancelar
-									</button>
-								</div>
-							</div>
-						</div>
+				<div class="flex items-center justify-between rounded-t-lg bg-emerald-700 p-4">
+					<span class="font-medium">{order.name}</span>
+				</div>
+				<div class="p-4">
+					<div class="mb-2 text-sm text-gray-400">
+						{getElapsedTime(order.createdAt)}
 					</div>
-				{/each}
+					<button
+						class="mb-2 w-full rounded bg-emerald-600 py-2 hover:bg-emerald-700"
+						on:click={() => openOrder(order.id)}
+					>
+						Adicionar items
+					</button>
+					{#if flag == 'admin'}
+						<button
+							class="w-full rounded bg-red-600 py-2 hover:bg-red-700"
+							on:click={() => openOrder(order.id)}
+						>
+							Cancelar
+						</button>
+					{/if}
+				</div>
 			</div>
-		</div>
-		<div class="mb-4 mt-4 flex justify-center">
-			<button
-				on:click={createCommand}
-				class="rounded-md bg-green-600 px-4 py-2 text-white transition-colors hover:bg-blue-700"
-			>
-				Adicionar Comanda
-			</button>
-		</div>
+		{/each}
+	</div>
+	<div class="mt-6 flex justify-center">
+		<button
+			class="rounded-md bg-green-600 px-4 py-2 text-white hover:bg-green-700"
+			on:click={() => (isCreatingOrder = true)}
+		>
+			Adicionar Comanda
+		</button>
 	</div>
 </div>
-{#if isAddingCommand}
+{#if isCreatingOrder}
 	<div class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
 		<div class="w-full max-w-md rounded-lg bg-gray-800 p-6 shadow-lg">
-			<h2 class="mb-4 text-lg font-semibold">Adicionar Novo Usuário</h2>
-			<form on:submit={handleAddUser} class="space-y-4">
+			<h2 class="mb-4 text-lg font-semibold">New Order</h2>
+			<form on:submit|preventDefault={createOrder} class="space-y-4">
 				<div>
 					<p class="mb-1 block text-sm text-gray-400">Nome</p>
 					<input
+						bind:value={customerName}
+						placeholder="Ex: John Doe"
 						class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
-						placeholder="Ex: johndoe"
 					/>
 				</div>
 				<div>
-					<p class="mb-1 block text-sm text-gray-400">(Opcional) Celular</p>
+					<p class="mb-1 block text-sm text-gray-400">Numero (optional)</p>
 					<input
-						class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
+						bind:value={customerPhone}
 						placeholder="(11) 99999-9999"
+						class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
 					/>
 				</div>
 
-				<div class="flex space-x-2">
+				<div class="flex justify-end space-x-2">
 					<button
 						type="button"
-						on:click={resetCommandForm}
+						on:click={() => (isCreatingOrder = false)}
 						class="rounded-lg bg-gray-700 px-4 py-2 hover:bg-gray-600"
 					>
 						Cancelar
@@ -311,7 +187,7 @@
 						type="submit"
 						class="flex items-center rounded-lg bg-emerald-600 px-4 py-2 hover:bg-emerald-700"
 					>
-						<img src={save_icon} alt="Salvar" class="mr-2 h-4 w-4" /> Salvar
+						<img src={save_icon} alt="Save" class="mr-2 h-4 w-4" /> Salvar
 					</button>
 				</div>
 			</form>

+ 7 - 0
src/lib/component/Product.svelte

@@ -428,6 +428,13 @@
 								placeholder="Ex: Cerveja..."
 							/>
 						</div>
+						<div>
+							<p class="mb-1 block text-sm text-gray-400">Descrição do Produto</p>
+							<input
+								class="w-full rounded-md border border-gray-600 bg-gray-700 px-3 py-2 focus:ring-emerald-500"
+								placeholder="Descricao"
+							/>
+						</div>
 
 						<div>
 							<p class="mb-1 block text-sm text-gray-400">Categoria</p>

+ 23 - 67
src/lib/component/Tables.svelte

@@ -26,16 +26,12 @@
 	};
 
 	let tables = [];
-
 	let orders = {};
-
 	let newTableNumber = '';
 	let showConfirmDelete = false;
 	let tableToDelete = null;
 
-	const getTableOrder = (tableId) => {
-		return orders[tableId];
-	};
+	const getTableOrder = (tableId) => orders[tableId];
 
 	const updateTableStatus = async (tableNumber, newStatus) => {
 		const requestOptions = {
@@ -44,7 +40,6 @@
 				'Content-Type': 'application/json',
 				Authorization: `Bearer ${token}`
 			},
-			redirect: 'follow',
 			body: JSON.stringify({
 				table_number: tableNumber,
 				company_id: company,
@@ -61,14 +56,10 @@
 
 	const startOrder = async (tableId, tableNumber) => {
 		await updateTableStatus(tableNumber, 'OCCUPIED');
-		tables = tables.map((t) => {
-			if (t.id === tableId) {
-				return { ...t, status: 'OCCUPIED', startTime: new Date().toISOString() };
-			}
-			return t;
-		});
+		tables = tables.map((t) =>
+			t.id === tableId ? { ...t, status: 'OCCUPIED', startTime: new Date().toISOString() } : t
+		);
 		orders = { ...orders, [tableId]: { items: [], totalAmount: 0 } };
-		console.log(`Order started for table ${tableId}`);
 	};
 
 	const getStatusColor = (status) => {
@@ -97,32 +88,17 @@
 		}
 	};
 
-	const getOrderTime = (startTime) => {
-		if (!startTime) return '';
-
-		const startDateTime = new Date(startTime);
-		const now = new Date();
-		const diff = Math.floor((now.getTime() - startDateTime.getTime()) / 1000 / 60);
-
-		if (diff < 60) {
-			return `${diff} min`;
-		} else {
-			const hours = Math.floor(diff / 60);
-			const mins = diff % 60;
-			return `${hours}h ${mins}m`;
-		}
-	};
-
 	const handleTableClick = async (tableId, tableNumber) => {
 		const table = tables.find((t) => t.id === tableId);
 		if (!table) return;
 
 		if (table.status === 'FREE') {
 			await startOrder(tableId, tableNumber);
+			localStorage.setItem('table', table.id);
 			goto('/dashboard/commands');
-		} else {
-			await goto(`/pos/${tableId}`);
 		}
+		localStorage.setItem('table', table.id);
+		goto('/dashboard/commands');
 	};
 
 	const openDeleteConfirm = (tableId, tableNumber) => {
@@ -144,7 +120,6 @@
 				'Content-Type': 'application/json',
 				Authorization: `Bearer ${token}`
 			},
-			redirect: 'follow',
 			body: JSON.stringify({
 				table_number: tableToDelete.number,
 				company_id: company
@@ -156,9 +131,8 @@
 			const result = await response.json();
 			if (result.status === 'ok') {
 				tables = tables.filter((t) => t.id !== tableToDelete.id);
-				const newOrders = { ...orders };
-				delete newOrders[tableToDelete.id];
-				orders = newOrders;
+				delete orders[tableToDelete.id];
+				orders = { ...orders };
 				showConfirmDelete = false;
 				tableToDelete = null;
 			} else {
@@ -176,7 +150,6 @@
 				'Content-Type': 'application/json',
 				Authorization: `Bearer ${token}`
 			},
-			redirect: 'follow',
 			body: JSON.stringify({ company_id: company })
 		};
 
@@ -207,20 +180,17 @@
 	const createTable = async () => {
 		if (!newTableNumber) return;
 
-		const payload = {
-			company_id: company,
-			table_number: newTableNumber,
-			status_id: 1
-		};
-
 		const requestOptions = {
 			method: 'POST',
 			headers: {
 				'Content-Type': 'application/json',
 				Authorization: `Bearer ${token}`
 			},
-			redirect: 'follow',
-			body: JSON.stringify(payload)
+			body: JSON.stringify({
+				company_id: company,
+				table_number: newTableNumber,
+				status_id: 1
+			})
 		};
 
 		try {
@@ -239,6 +209,9 @@
 
 	onMount(() => {
 		fetchTables();
+		setInterval(() => {
+			fetchTables();
+		}, 5000);
 	});
 </script>
 
@@ -276,29 +249,12 @@
 
 					<div class="p-4">
 						{#if table.status !== 'FREE' && order}
-							<div class="space-y-3">
-								<!-- <div class="flex justify-between text-sm">
-									<span class="text-gray-400">{getOrderTime(table.startTime)}</span>
-									<div class="font-medium">
-										{order.items.length}
-										{order.items.length === 1 ? 'item' : 'itens'}
-									</div>
-								</div> -->
-
-								<!-- <div class="flex justify-between text-sm">
-									<span class="text-gray-400">Total:</span>
-									<span class="font-medium">
-										R$ {order.totalAmount.toFixed(2)}
-									</span>
-								</div> -->
-
-								<button
-									on:click={() => handleTableClick(table.id, table.number)}
-									class="mt-2 flex w-full items-center justify-center rounded bg-indigo-600 px-3 py-2 text-sm transition-colors hover:bg-indigo-700"
-								>
-									Detalhes Mesa
-								</button>
-							</div>
+							<button
+								on:click={() => handleTableClick(table.id, table.number)}
+								class="mt-2 flex w-full items-center justify-center rounded bg-indigo-600 px-3 py-2 text-sm transition-colors hover:bg-indigo-700"
+							>
+								Detalhes Mesa
+							</button>
 						{:else}
 							<div class="flex flex-col items-center justify-center space-y-2 py-4">
 								<button

+ 1 - 0
src/routes/login/+page.svelte

@@ -50,6 +50,7 @@
 			const company = data.data.company_id;
 			localStorage.setItem('token', token);
 			localStorage.setItem('company', company);
+			localStorage.setItem('user', username);
 			console.log(data);
 			if (data.status === 'ok') {
 				const id = data.data.role_id;