Skip to content

Commit

Permalink
FEAT: add quotes
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdelilahOu committed May 28, 2024
1 parent 2e8e9df commit d21c0fb
Show file tree
Hide file tree
Showing 22 changed files with 1,390 additions and 53 deletions.
3 changes: 2 additions & 1 deletion .eslintrc-auto-import.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
"watchTriggerable": true,
"watchWithFilter": true,
"whenever": true,
"getFileBytes": true
"getFileBytes": true,
"CreateQuoteSchema": true
}
}
1 change: 1 addition & 0 deletions auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare global {
const CreateInvoiceSchema: typeof import('./src/schemas/invoice.schema')['CreateInvoiceSchema']
const CreateOrderSchema: typeof import('./src/schemas/order.schema')['CreateOrderSchema']
const CreateProductSchema: typeof import('./src/schemas/products.schema')['CreateProductSchema']
const CreateQuoteSchema: typeof import('./src/schemas/quote.schema')['CreateQuoteSchema']
const CreateSupplierSchema: typeof import('./src/schemas/supplier.schema')['CreateSupplierSchema']
const EffectScope: typeof import('vue')['EffectScope']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
Expand Down
1 change: 0 additions & 1 deletion src-tauri/service/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,6 @@ impl QueriesService {
None => Err(DbErr::RecordNotFound(String::from("no invoice"))),
}
}

//
pub async fn list_inventory(db: &DbConn, args: ListArgs) -> Result<JsonValue, DbErr> {
let count = InventoryMouvements::find()
Expand Down
12 changes: 9 additions & 3 deletions src/components/InvoiceCreate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,15 @@ const hideModal = () => {
<SelectValue placeholder="Select a status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="PAID"> Paid </SelectItem>
<SelectItem value="CANCELED"> Cancelled </SelectItem>
<SelectItem value="PENDING"> Pending </SelectItem>
<SelectItem value="PAID">
{{ t("g.status.paid") }}
</SelectItem>
<SelectItem value="CANCELED">
{{ t("g.status.cancelled") }}
</SelectItem>
<SelectItem value="PENDING">
{{ t("g.status.pending") }}
</SelectItem>
</SelectContent>
</Select>
</div>
Expand Down
12 changes: 9 additions & 3 deletions src/components/InvoiceUpdate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,15 @@ const deleteInvoiceItem = (index: number) => {
<SelectValue placeholder="Select a status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="PAID"> Paid </SelectItem>
<SelectItem value="CANCELED"> Cancelled </SelectItem>
<SelectItem value="PENDING"> Pending </SelectItem>
<SelectItem value="PAID">
{{ t("g.status.paid") }}
</SelectItem>
<SelectItem value="CANCELED">
{{ t("g.status.cancelled") }}
</SelectItem>
<SelectItem value="PENDING">
{{ t("g.status.pending") }}
</SelectItem>
</SelectContent>
</Select>
</div>
Expand Down
14 changes: 11 additions & 3 deletions src/components/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ const { t } = useI18n();
class="w-full h-full flex items-center py-3 px-2 bg-white justify-between"
>
<div class="text-black flex items-center justify-center gap-2">
<ChevronLeft class="cursor-pointer" @click="$router.back()" />
<ChevronRight class="cursor-pointer" @click="$router.forward()" />
<ChevronLeft
:size="20"
class="cursor-pointer"
@click="$router.back()"
/>
<ChevronRight
:size="20"
class="cursor-pointer"
@click="$router.forward()"
/>
<RouterLink to="/">
<HomeIcon :size="22" class="bg-white" />
<HomeIcon :size="18" class="bg-white" />
</RouterLink>
<!-- <span class="pb-[3px] text-gray-700 flex items-center"> -->
<!-- <span v-if="route.fullPath !== '/'" class="flex items-center">
Expand Down
12 changes: 9 additions & 3 deletions src/components/OrderCreate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,15 @@ const hideModal = () => {
<SelectValue placeholder="Select a status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="DELIVERED"> Delivered </SelectItem>
<SelectItem value="CANCELED"> Cancelled </SelectItem>
<SelectItem value="PENDING"> Pending </SelectItem>
<SelectItem value="DELIVERED">
{{ t("g.status.delivered") }}
</SelectItem>
<SelectItem value="CANCELED">
{{ t("g.status.cancelled") }}
</SelectItem>
<SelectItem value="PENDING">
{{ t("g.status.pending") }}
</SelectItem>
</SelectContent>
</Select>
</div>
Expand Down
12 changes: 9 additions & 3 deletions src/components/OrderUpdate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,15 @@ const deleteOrderItem = (index: number) => {
<SelectValue placeholder="Select a status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="DELIVERED"> Delivered </SelectItem>
<SelectItem value="CANCELED"> Cancelled </SelectItem>
<SelectItem value="PENDING"> Pending </SelectItem>
<SelectItem value="DELIVERED">
{{ t("g.status.delivered") }}
</SelectItem>
<SelectItem value="CANCELED">
{{ t("g.status.cancelled") }}
</SelectItem>
<SelectItem value="PENDING">
{{ t("g.status.pending") }}
</SelectItem>
</SelectContent>
</Select>
</div>
Expand Down
207 changes: 207 additions & 0 deletions src/components/QuoteCreate.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
<script setup lang="ts">
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useUpdateRouteQueryParams } from "@/composables/useUpdateQuery";
import type { QuoteForCreateT } from "@/schemas/quote.schema";
import { store } from "@/store";
import type { Res } from "@/types";
import { invoke } from "@tauri-apps/api";
import { Trash2 } from "lucide-vue-next";
import { error, info } from "tauri-plugin-log-api";
import { reactive, ref } from "vue";
import { useI18n } from "vue-i18n";
import { toast } from "vue-sonner";
import SearchableItems from "./ui/UISearchableItems.vue";
import UiModalCard from "./ui/UiModalCard.vue";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
import { Separator } from "./ui/separator";
const { t } = useI18n();
const { updateQueryParams } = useUpdateRouteQueryParams();
const clients = ref<{ label: string; value: string }[]>([]);
const products = ref<{ label: string; value: string }[]>([]);
const isLoading = ref<boolean>(false);
const quote = reactive<QuoteForCreateT>({
clientId: "",
items: [
{
product_id: undefined,
quantity: undefined,
price: undefined,
},
],
});
const addQuoteItem = () => {
quote.items?.push({
product_id: undefined,
quantity: undefined,
price: undefined,
});
};
const deleteQuoteItem = (index: number) => {
quote.items?.splice(index, 1);
};
const searchClients = async (search: string | number) => {
const res = await invoke<Res<{ label: string; value: string }[]>>(
"search_clients",
{
search,
},
);
if (!res.error) {
clients.value = res.data;
}
};
const searchProducts = async (search: string | number) => {
const res = await invoke<Res<{ label: string; value: string }[]>>(
"search_products",
{
search,
},
);
if (!res.error) {
products.value = res.data;
}
};
const createQuote = async () => {
isLoading.value = true;
if (quote?.clientId && quote.items?.length !== 0) {
try {
const quoteRes = await invoke<Res<String>>("create_quote", {
quote: {
client_id: quote.clientId,
},
});
for await (const item of quote.items) {
const invRes = await invoke<Res<string>>("create_inventory", {
mvm: {
mvm_type: "OUT",
product_id: item.product_id,
quantity: item.quantity,
},
});
await invoke<Res<string>>("create_quote_item", {
item: {
quote_id: quoteRes.data,
inventory_id: invRes.data,
price: item.price,
},
});
}
//
info(`CREATE QUOTE: ${JSON.stringify(quote)}`);
//
toast(t("notifications.quote.created"), {
closeButton: true,
});
// toggle refresh
updateQueryParams({
refresh: "refresh-create-" + Math.random() * 9999,
});
} catch (err: any) {
error("CREATE QUOTE: " + err.error);
} finally {
isLoading.value = false;
hideModal();
}
return;
}
isLoading.value = false;
};
const hideModal = () => {
store.setters.updateStore({ key: "show", value: false });
};
</script>

<template>
<UiModalCard
class="w-5/6 lg:w-1/2 rounded-md relative h-fit z-50 gap-3 flex flex-col bg-white p-2 min-w-[350px]"
>
<template #title>
{{ t("o.c.title") }}
</template>
<template #content>
<div class="h-full w-full grid grid-cols-1 gap-2">
<div class="flex w-full h-fit gap-1">
<div class="w-full h-full flex flex-col gap-1">
<Label for="client_id">
{{ t("o.c.d.s.title") }}
</Label>
<SearchableItems
:items="clients"
@update:items="(s) => searchClients(s)"
@on:select="(id) => (quote.clientId = id)"
/>
</div>
</div>
<Separator />
<div class="w-full h-full flex flex-col gap-1">
<Label for="products">
{{ t("o.c.d.o.products") }}
</Label>
<Button @click="addQuoteItem">
{{ t("o.c.d.o.add") }}
</Button>
<div
class="products w-full grid pt-1 grid-cols-[1fr_1fr_1fr_36px] items-center overflow-auto scrollbar-thin scrollbar-thumb-transparent max-h-64 gap-1"
>
<template v-for="(item, index) in quote.items" :key="index">
<SearchableItems
:items="products"
@update:items="(s) => searchProducts(s)"
@on:select="
(id, price) => ((item.product_id = id), (item.price = price))
"
/>
<Input
class="border-r-0"
:placeHolder="t('o.c.d.o.placeholder[0]')"
type="number"
v-model="item.quantity"
>
<template #unite> Item </template>
</Input>
<Input
class="border-r-0"
:placeHolder="t('o.c.d.o.placeholder[1]')"
type="number"
v-model="item.price"
>
<template #unite> DH </template>
</Input>
<Trash2
@click="deleteQuoteItem(index)"
class="cursor-pointer"
:size="22"
/>
</template>
</div>
</div>
</div>
</template>
<template #footer>
<div class="grid w-full grid-cols-3 gap-2">
<Button @click="hideModal" variant="outline">
{{ t("g.b.no") }}
</Button>
<Button class="col-span-2" @click="createQuote()">
{{ t("g.b.c") }}
</Button>
</div>
</template>
</UiModalCard>
</template>
59 changes: 59 additions & 0 deletions src/components/QuoteDelete.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script setup lang="ts">
import { useUpdateRouteQueryParams } from "@/composables/useUpdateQuery";
import { useI18n } from "vue-i18n";
import { invoke } from "@tauri-apps/api";
import { Button } from "./ui/button";
import { store } from "@/store";
import UiModalCard from "./ui/UiModalCard.vue";
import { error, info } from "tauri-plugin-log-api";
import type { Res } from "@/types";
import { toast } from "vue-sonner";
const { t } = useI18n();
const { updateQueryParams } = useUpdateRouteQueryParams();
const deleteTheQuotes = async (id: string) => {
try {
await invoke<Res<any>>("delete_quote", { id });
//
info(`DELETE QUOTE: ${id}`);
//
toast(t("notifications.quote.deleted"), {
closeButton: true,
});
// toggle refresh
updateQueryParams({
refresh: "refresh-delete-" + Math.random() * 9999,
});
} catch (err: any) {
error("DELETE QUOTE: " + err.error);
} finally {
store.setters.updateStore({ key: "show", value: false });
}
};
const cancelDelete = () => {
store.setters.updateStore({ key: "show", value: false });
};
</script>

<template>
<UiModalCard>
<template #title>
{{ t("o.d.title") }}n° {{ $route.query?.id }} ?
</template>
<template #footer>
<div class="grid grid-cols-3 gap-2">
<Button variant="outline" @click="cancelDelete">
{{ t("g.b.no") }}
</Button>
<Button
class="col-span-2"
@click="deleteTheQuotes($route.query?.id as string)"
>
{{ t("g.b.d") }}
</Button>
</div>
</template>
</UiModalCard>
</template>
Loading

0 comments on commit d21c0fb

Please sign in to comment.