-
Notifications
You must be signed in to change notification settings - Fork 0
/
useSaveOrder.ts
108 lines (90 loc) · 2.7 KB
/
useSaveOrder.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import {
addDoc,
collection,
doc,
DocumentReference,
DocumentSnapshot,
getDoc,
updateDoc,
} from "@firebase/firestore";
import { useCallback } from "react";
import { useFirestore, useUser } from "reactfire";
import { Buyer } from "../components/OrderDetailsModal";
import { CartData } from "../providers/CartProvider";
import { FullItem } from "./types";
export type FullOrder = {
items: (CartData & { price: number | null })[];
total: number;
buyer: Buyer;
date: string;
};
type ItemDocument = {
snapshot: DocumentSnapshot<FullItem>;
quantity: number;
};
export const useSaveOrder = () => {
const firestore = useFirestore();
const orders = collection(firestore, "orders");
const { data: user } = useUser();
return useCallback(
async (items: CartData[], buyer: Buyer) => {
const itemsIds = new Set(items.map(({ uniqueId }) => uniqueId));
const documents: Map<string, ItemDocument | null> = new Map(
await Promise.all(
Array.from(itemsIds.values()).map(async (uniqueId) => {
try {
const snapshot = await getDoc(
doc(firestore, "items", uniqueId) as DocumentReference<FullItem>
);
return [uniqueId, { snapshot, quantity: 0 }] as [
string,
ItemDocument
];
} catch (e) {
return [uniqueId, null] as [string, null];
}
})
)
);
const itemsWithPrice = items.map((item) => {
const document = documents.get(item.uniqueId);
if (!document || !document.snapshot.exists())
return { ...item, price: null };
const { price, discount = 0 } = document.snapshot.data();
document.quantity += item.quantity;
return {
...item,
price: price * (1 - discount),
};
});
await Promise.all(
Array.from(documents.values()).map(async (value) => {
if (!value) return;
const { snapshot, quantity } = value;
if (!snapshot.exists()) return;
try {
const stock = Math.max(0, snapshot.data().stock - quantity);
updateDoc(snapshot.ref, {
stock,
display: stock !== 0,
});
} catch (e) {
console.error(e);
}
})
);
const order = await addDoc(orders, {
items: itemsWithPrice,
buyer,
user: user?.uid ?? null,
total: itemsWithPrice.reduce(
(a, b) => a + (b.price ?? 0) * b.quantity,
0 as number
),
date: new Date().toISOString(),
} as FullOrder);
return order.id;
},
[orders, firestore, user]
);
};