mirror of
https://github.com/beak-insights/felicity-lims.git
synced 2025-02-24 00:42:59 +08:00
194 lines
10 KiB
TypeScript
194 lines
10 KiB
TypeScript
import { defineComponent, computed, ref, defineAsyncComponent } from 'vue';
|
|
import { AddStockOrderDocument, AddStockOrderMutation, AddStockOrderMutationVariables } from '@/graphql/operations/inventory.mutations';
|
|
import useApiUtil from '@/composables/api_util';
|
|
import { useInventoryStore } from '@/stores/inventory';
|
|
import { useStorageStore } from '@/stores/storage';
|
|
import { useSetupStore } from '@/stores/setup';
|
|
import { useUserStore } from '@/stores/user';
|
|
const Drawer = defineAsyncComponent(
|
|
() => import('@/components/ui/FelDrawer.vue')
|
|
)
|
|
const PageHeading = defineAsyncComponent(
|
|
() => import('@/components/common/FelPageHeading.vue')
|
|
)
|
|
const InventoryAdjustments = defineAsyncComponent(
|
|
() => import('./InvAdjustments')
|
|
)
|
|
const InventoryListing = defineAsyncComponent(
|
|
() => import('./InvListing')
|
|
)
|
|
const InventoryOrders = defineAsyncComponent(
|
|
() => import('./InvOrders')
|
|
)
|
|
|
|
const InventoryHome = defineComponent({
|
|
name: 'inventory-home',
|
|
setup() {
|
|
const { withClientMutation } = useApiUtil();
|
|
|
|
// Prefetch data
|
|
const inventoryStore = useInventoryStore();
|
|
const setupStore = useSetupStore();
|
|
const storageStore = useStorageStore();
|
|
const userStore = useUserStore();
|
|
inventoryStore.fetchItems({
|
|
first: 10000,
|
|
after: '',
|
|
text: '',
|
|
sortBy: ['-uid'],
|
|
});
|
|
userStore.fetchUsers({});
|
|
setupStore.fetchSuppliers();
|
|
setupStore.fetchDepartments({});
|
|
inventoryStore.fetchCategories();
|
|
inventoryStore.fetchHazards();
|
|
storageStore.fetchStoreRooms();
|
|
inventoryStore.fetchUnits();
|
|
|
|
const currentTab = ref('orders');
|
|
const inventoryTabs = ref(['orders', 'products', 'ledger']);
|
|
const currentTabComponent = computed(() => 'tab-' + currentTab.value);
|
|
|
|
const viewBasket = ref(false);
|
|
|
|
return {
|
|
currentTab,
|
|
inventoryTabs,
|
|
currentTabComponent,
|
|
basket: computed(() => inventoryStore.getBasket),
|
|
viewBasket,
|
|
inventoryStore,
|
|
createOrder: () => {
|
|
const basket = inventoryStore.getBasket;
|
|
withClientMutation<AddStockOrderMutation, AddStockOrderMutationVariables>(AddStockOrderDocument,
|
|
{
|
|
payload: {
|
|
orderProducts: basket.map(order => ({
|
|
productUid: order.product.uid,
|
|
stockLotUid: order.stockLotUid,
|
|
quantity: order.quantity,
|
|
remarks: '',
|
|
})),
|
|
departmentUid: undefined,
|
|
},
|
|
},
|
|
'createStockOrder'
|
|
).then(result => {
|
|
inventoryStore.addStockOrder(result?.stockOrder);
|
|
inventoryStore.clearBasket();
|
|
viewBasket.value = false;
|
|
});
|
|
},
|
|
};
|
|
},
|
|
render() {
|
|
return (
|
|
<>
|
|
<PageHeading title="Inventory Management" />
|
|
<section class="col-span-12 mt-2">
|
|
<nav class="flex justify-between bg-white shadow-md mt-2">
|
|
<div class="-mb-px flex justify-start">
|
|
{this.inventoryTabs?.map(tab => (
|
|
<a
|
|
key={tab}
|
|
class={[
|
|
'no-underline text-gray-500 uppercase tracking-wide font-bold text-xs py-1 px-4 tab hover:bg-sky-600 hover:text-gray-200',
|
|
{ 'tab-active': this.currentTab === tab },
|
|
]}
|
|
onClick={() => (this.currentTab = tab)}
|
|
|
|
>
|
|
{tab}
|
|
</a>
|
|
))}
|
|
</div>
|
|
{this.basket.length > 0 && (
|
|
<button type="button" class="flex items-center mr-4" onClick={() => (this.viewBasket = true)}>
|
|
<span class="mr-2">View</span> <font-awesome-icon icon="cart-shopping" />
|
|
</button>
|
|
)}
|
|
</nav>
|
|
|
|
<div>
|
|
{this.currentTab === 'orders' && <InventoryOrders />}
|
|
{this.currentTab === 'products' && <InventoryListing />}
|
|
{this.currentTab === 'ledger' && <InventoryAdjustments />}
|
|
</div>
|
|
|
|
<Drawer show={this.viewBasket} onClose={() => (this.viewBasket = false)}>
|
|
{{
|
|
header: () => 'Your Order Basket',
|
|
body: () => (
|
|
<>
|
|
<div class="overflow-x-auto mt-2 mb-4">
|
|
<div class="align-middle inline-block min-w-full shadow overflow-hidden bg-white shadow-dashboard px-2 pt-1 rounded-bl-lg rounded-br-lg">
|
|
<table class="min-w-full">
|
|
<thead>
|
|
<tr>
|
|
<th class="px-1 py-1 border-b-2 border-gray-300 text-left leading-4 text-gray-800 tracking-wider">
|
|
Product Name
|
|
</th>
|
|
<th class="px-1 py-1 border-b-2 border-gray-300 text-left text-sm leading-4 text-gray-800 tracking-wider">
|
|
Lot Number
|
|
</th>
|
|
<th class="px-1 py-1 border-b-2 border-gray-300 text-left text-sm leading-4 text-gray-800 tracking-wider">
|
|
Quantity
|
|
</th>
|
|
<th class="px-1 py-1 border-b-2 border-gray-300 text-left leading-4 text-gray-800 tracking-wider"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white">
|
|
{this.basket.map(item => (
|
|
<tr key={item.product.uid} v-motion-slide-right>
|
|
<td>
|
|
<p>{item.product.name}</p>
|
|
</td>
|
|
<td>
|
|
<p>{item.stockLot?.lotNumber}</p>
|
|
</td>
|
|
<td class="px-1 py-1 whitespace-no-wrap">
|
|
<label class="block">
|
|
<input
|
|
class="form-input"
|
|
type="number"
|
|
v-model={item.quantity}
|
|
placeholder={item.quantity}
|
|
/>
|
|
</label>
|
|
</td>
|
|
<td class="px-1 whitespace-no-wrap">
|
|
<button
|
|
type="button"
|
|
class="bg-sky-800 text-white rounded-sm leading-none px-2 py-1"
|
|
onClick={() => this.inventoryStore.removeFromBasket(item.product.uid)}
|
|
>
|
|
Remove
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<hr />
|
|
<button
|
|
type="button"
|
|
class="mt-4 bg-sky-800 text-white rounded-sm leading-none px-2 py-1"
|
|
onClick={() => this.createOrder()}
|
|
>
|
|
Create Order
|
|
</button>
|
|
</>
|
|
),
|
|
footer: () => [],
|
|
}}
|
|
</Drawer>
|
|
</section>
|
|
</>
|
|
);
|
|
},
|
|
});
|
|
|
|
export { InventoryHome };
|
|
export default InventoryHome
|