@pol-studios/features 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,128 @@
1
+ // src/ordering/useOrderHint.ts
2
+ import { isUsable } from "@pol-studios/utils";
3
+ var useOrderHint = () => {
4
+ const createOrderHint = (prevOrderHint, nextOrderHint) => {
5
+ let newOrderHint;
6
+ if (isNaN(prevOrderHint)) {
7
+ return 1;
8
+ }
9
+ if (isUsable(nextOrderHint) === false || isNaN(nextOrderHint)) {
10
+ newOrderHint = prevOrderHint + 1;
11
+ } else if (isUsable(prevOrderHint) === false) {
12
+ newOrderHint = nextOrderHint / 2;
13
+ } else {
14
+ newOrderHint = (prevOrderHint + nextOrderHint) / 2;
15
+ }
16
+ return newOrderHint;
17
+ };
18
+ return { createOrderHint };
19
+ };
20
+ var useOrderHint_default = useOrderHint;
21
+
22
+ // src/ordering/useOrderManager.ts
23
+ import { useEffect, useState } from "react";
24
+ import {
25
+ useDbRealtimeQuery,
26
+ useDbUpsert,
27
+ useSupabase
28
+ } from "@pol-studios/db";
29
+ import { isUsable as isUsable2 } from "@pol-studios/utils";
30
+ var useOrderManager = (table, items, property, schema = "public") => {
31
+ const [managedItems, setManagedItems] = useState([]);
32
+ const [originalItems, setOriginalItems] = useState([]);
33
+ const supabase = useSupabase();
34
+ const upsert = useDbUpsert(schema !== "public" ? { table, schema } : table, [
35
+ "id"
36
+ ]);
37
+ const orderHintRequest = property ? useDbRealtimeQuery(
38
+ supabase.schema(schema).from(table).select("*", { count: "exact" }).in(
39
+ property,
40
+ items.map((x) => x.id)
41
+ )
42
+ ) : null;
43
+ useEffect(() => {
44
+ if (!property) {
45
+ const res2 = [];
46
+ (async () => {
47
+ for (const [index, item] of items.entries()) {
48
+ if (item.orderHint == null) {
49
+ await updateOrderHint(
50
+ item,
51
+ index > 0 ? Number(res2[index - 1].orderHint) : null,
52
+ null
53
+ );
54
+ }
55
+ res2.push({
56
+ ...item,
57
+ orderHint: Number(item.orderHint ?? index + 1)
58
+ });
59
+ }
60
+ res2.sort((a, b) => a.orderHint - b.orderHint);
61
+ setOriginalItems(res2);
62
+ setManagedItems(res2);
63
+ })();
64
+ return;
65
+ }
66
+ if (!orderHintRequest?.data) return;
67
+ const dataWithOrderHint = orderHintRequest.data;
68
+ let currMax = dataWithOrderHint.map((x) => Number(x.orderHint)).reduce((a, b) => Math.max(a, b), 0);
69
+ const res = [];
70
+ (async () => {
71
+ for (const item of items) {
72
+ const newItem = { ...item, orderHint: void 0 };
73
+ const orderHint = dataWithOrderHint.find(
74
+ (x) => x[property] === item.id
75
+ );
76
+ if (isUsable2(orderHint)) {
77
+ newItem.orderHint = Number(orderHint.orderHint);
78
+ } else {
79
+ await upsert.mutateAsync({
80
+ orderHint: String(currMax + 1),
81
+ [property]: item.id
82
+ });
83
+ currMax += 1;
84
+ newItem.orderHint = currMax;
85
+ }
86
+ res.push(newItem);
87
+ }
88
+ res.sort((a, b) => a.orderHint - b.orderHint);
89
+ setOriginalItems(res);
90
+ setManagedItems(res);
91
+ })();
92
+ }, [orderHintRequest?.data, items, property]);
93
+ const orderHintHelper = useOrderHint_default();
94
+ const updateOrderHint = async (activeItem, prevOrderHint, nextOrderHint) => {
95
+ let newOrderHint = orderHintHelper.createOrderHint(
96
+ prevOrderHint,
97
+ nextOrderHint
98
+ );
99
+ const newActiveItem = { ...activeItem, orderHint: newOrderHint };
100
+ const newManagedItems = managedItems.map(
101
+ (x) => x.id === activeItem.id ? newActiveItem : x
102
+ );
103
+ newManagedItems.sort((a, b) => a.orderHint - b.orderHint);
104
+ setManagedItems(newManagedItems);
105
+ if (!property) {
106
+ await upsert.mutateAsync({
107
+ id: activeItem.id,
108
+ orderHint: String(newOrderHint)
109
+ });
110
+ return;
111
+ }
112
+ try {
113
+ const dataWithOrderHint = orderHintRequest?.data;
114
+ const data = dataWithOrderHint?.find(
115
+ (x) => x[property] === activeItem.id
116
+ );
117
+ await upsert.mutateAsync({ ...data, orderHint: String(newOrderHint) });
118
+ } catch (error) {
119
+ setManagedItems(originalItems);
120
+ }
121
+ };
122
+ return { managedItems, updateOrderHint };
123
+ };
124
+ var useOrderManager_default = useOrderManager;
125
+ export {
126
+ useOrderHint_default as useOrderHint,
127
+ useOrderManager_default as useOrderManager
128
+ };
@@ -0,0 +1,36 @@
1
+ // src/punch-list/usePunchListPage.ts
2
+ import {
3
+ useSupabase
4
+ } from "@pol-studios/db";
5
+ import { useEffect, useState } from "react";
6
+ import { useDbUpsert } from "@pol-studios/db";
7
+ import { useAuth } from "@pol-studios/auth";
8
+ function usePunchListPage(relation, entityId) {
9
+ const supabase = useSupabase();
10
+ const upsert = useDbUpsert("PunchListPage", ["id"]);
11
+ const { user } = useAuth();
12
+ const [punchListPageId, setPunchListPageId] = useState(null);
13
+ const handleThis = async () => {
14
+ const punchListPage = await supabase.from("PunchListPage").select("id").eq("tableName", relation).eq("entityId", entityId).maybeSingle();
15
+ if (punchListPage.data) {
16
+ setPunchListPageId(punchListPage.data.id);
17
+ return;
18
+ }
19
+ await upsert.mutateAsync({
20
+ tableName: relation,
21
+ entityId,
22
+ createdBy: user?.id
23
+ });
24
+ const newPunchListPage = await supabase.from("PunchListPage").select("id").eq("tableName", relation).eq("entityId", entityId).maybeSingle();
25
+ if (newPunchListPage.data) {
26
+ setPunchListPageId(newPunchListPage.data.id);
27
+ }
28
+ };
29
+ useEffect(() => {
30
+ handleThis();
31
+ }, [entityId]);
32
+ return punchListPageId;
33
+ }
34
+ export {
35
+ usePunchListPage
36
+ };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@pol-studios/features",
3
+ "version": "1.0.0",
4
+ "description": "Feature modules for POL applications",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": ["dist"],
10
+ "exports": {
11
+ ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" },
12
+ "./comments": { "import": "./dist/comments/index.js", "types": "./dist/comments/index.d.ts" },
13
+ "./ordering": { "import": "./dist/ordering/index.js", "types": "./dist/ordering/index.d.ts" },
14
+ "./punch-list": { "import": "./dist/punch-list/index.js", "types": "./dist/punch-list/index.d.ts" },
15
+ "./filter-utils": { "import": "./dist/filter-utils/index.js", "types": "./dist/filter-utils/index.d.ts" }
16
+ },
17
+ "keywords": ["features", "comments", "ordering", "punch-list"],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "typecheck": "tsc --noEmit",
22
+ "prepublishOnly": "pnpm build"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "dependencies": {
28
+ "moment": "^2.30.1"
29
+ },
30
+ "peerDependencies": {
31
+ "@pol-studios/db": ">=1.0.0",
32
+ "@pol-studios/auth": ">=1.0.0",
33
+ "@pol-studios/utils": ">=1.0.0",
34
+ "react": "^18.0.0 || ^19.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@pol-studios/db": "workspace:*",
38
+ "@pol-studios/auth": "workspace:*",
39
+ "@pol-studios/utils": "workspace:*",
40
+ "tsup": "^8.0.0",
41
+ "typescript": "^5.0.0"
42
+ }
43
+ }