Skip to content

Commit d4e617c

Browse files
authored
Add Checkout Groups (#738)
1 parent 494af1a commit d4e617c

File tree

11 files changed

+104
-146
lines changed

11 files changed

+104
-146
lines changed

common/types/Library.d.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,29 @@ export default interface Library {
102102
4: string;
103103
5: string;
104104
};
105+
/**
106+
* Groups for maximum checkouts and renews
107+
*/
108+
checkoutGroups: {
109+
[key: string]: {
110+
/**
111+
* The maximum number of checkouts allowed.
112+
*/
113+
maxCheckouts: number;
114+
/**
115+
* The maximum number of renews allowed.
116+
*/
117+
maxRenews: number;
118+
/**
119+
* Renew duration in days.
120+
*/
121+
renewDuration: number;
122+
/**
123+
* Default checkout duration in days.
124+
*/
125+
checkoutDuration: number;
126+
};
127+
};
105128
/**
106129
* The UID of the user who owns this library.
107130
*/

common/types/User.d.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@ export default interface User {
99
*/
1010
activeCheckouts: string[];
1111
/**
12-
* The maximum number of checkouts the user is allowed to have
12+
* The checkout group of the user.
1313
*/
14-
maxCheckouts: number;
15-
/**
16-
* The maximum number of renews the user is allowed to have
17-
*/
18-
maxRenews: number;
14+
checkoutGroup: string;
1915
/**
2016
* The user's first name
2117
*/
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"kind":"identitytoolkit#DownloadAccountResponse","users":[{"localId":"yEjjsFDWcKIxWgXSWfb71XlGpYdN","createdAt":"1621181611766","lastLoginAt":"1658417099640","displayName":"","photoUrl":"","passwordHash":"fakeHash:salt=fakeSaltMRmWNZYR2cyN9tqJkg7N:password=bsclibrary","salt":"fakeSaltMRmWNZYR2cyN9tqJkg7N","passwordUpdatedAt":1659921208629,"customAttributes":"{\"permissions\":{},\"librariesJoined\":[\"bsclibrary\"],\"librariesOwned\":[\"bsclibrary\"]}","providerUserInfo":[{"providerId":"password","email":"admin@bsclibrary.net","federatedId":"admin@bsclibrary.net","rawId":"admin@bsclibrary.net","displayName":"","photoUrl":""}],"validSince":"1659921208","email":"admin@bsclibrary.net","emailVerified":true,"disabled":false,"lastRefreshAt":"2022-08-08T01:13:28.629Z"}]}
1+
{"kind":"identitytoolkit#DownloadAccountResponse","users":[{"localId":"yEjjsFDWcKIxWgXSWfb71XlGpYdN","createdAt":"1621181611766","lastLoginAt":"1659929396021","displayName":"","photoUrl":"","passwordHash":"fakeHash:salt=fakeSaltMRmWNZYR2cyN9tqJkg7N:password=bsclibrary","salt":"fakeSaltMRmWNZYR2cyN9tqJkg7N","passwordUpdatedAt":1659929194854,"customAttributes":"{\"permissions\":{},\"librariesJoined\":[\"bsclibrary\"],\"librariesOwned\":[\"bsclibrary\"]}","providerUserInfo":[{"providerId":"password","email":"admin@bsclibrary.net","federatedId":"admin@bsclibrary.net","rawId":"admin@bsclibrary.net","displayName":"","photoUrl":""}],"validSince":"1659929194","email":"admin@bsclibrary.net","emailVerified":true,"disabled":false,"lastRefreshAt":"2022-08-08T03:29:56.021Z"}]}
Binary file not shown.
277 Bytes
Binary file not shown.
Binary file not shown.

functions/src/checkouts/renewCheckout.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import renewCheckoutData from '@common/functions/renewCheckout';
55
import Checkout from '@common/types/Checkout';
66
import RecursivePartial from '@common/types/util/RecursivePartial';
77
import User from '@common/types/User';
8+
import Library from '@common/types/Library';
89

910
const renewCheckout = functions
1011
.region('us-west2')
@@ -44,6 +45,8 @@ const renewCheckout = functions
4445
throw new functions.https.HttpsError('not-found', `Library not found.`);
4546
}
4647

48+
const library: Library = libraryDoc.data() as Library;
49+
4750
const userDoc = await firestore
4851
.collection('libraries')
4952
.doc(data.libraryID)
@@ -87,7 +90,11 @@ const renewCheckout = functions
8790
`The checkout with ID ${data.checkoutID} does not belong to the user.`
8891
);
8992
}
90-
if (user.maxRenews - checkout.renewsUsed <= 0) {
93+
if (
94+
library.checkoutGroups[user.checkoutGroup].maxRenews -
95+
checkout.renewsUsed <=
96+
0
97+
) {
9198
throw new functions.https.HttpsError(
9299
'permission-denied',
93100
`The checkout with ID ${data.checkoutID} has already been renewed the maximum number of times.`
@@ -96,7 +103,12 @@ const renewCheckout = functions
96103

97104
const newCheckout: RecursivePartial<Checkout> = {
98105
dueDate: Timestamp.fromMillis(
99-
checkout.dueDate.toDate().valueOf() + 7 * 24 * 60 * 60 * 1000
106+
checkout.dueDate.toDate().valueOf() +
107+
library.checkoutGroups[user.checkoutGroup].renewDuration *
108+
24 *
109+
60 *
110+
60 *
111+
1000
100112
),
101113
// Since we can not increment the dueDate, we will not increment the renewsUsed
102114
renewsUsed: checkout.renewsUsed + 1,

react/src/pages/Account/Checkouts.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import Checkout from '@common/types/Checkout';
2121
import NotificationContext from 'src/contexts/NotificationContext';
2222
import ActiveLibraryID from 'src/contexts/ActiveLibraryID';
2323
import User from '@common/types/User';
24+
import Library from '@common/types/Library';
2425

2526
const CheckoutRow = ({ checkoutID }: { checkoutID: string }) => {
2627
const NotificationHandler = useContext(NotificationContext);
@@ -33,6 +34,10 @@ const CheckoutRow = ({ checkoutID }: { checkoutID: string }) => {
3334
const user = useUser().data;
3435
if (!user) throw new Error('No user signed in!');
3536

37+
const libraryDoc: Library = useFirestoreDocData(
38+
doc(firestore, 'libraries', activeLibraryID)
39+
).data as Library;
40+
3641
const userDoc: User = useFirestoreDocData(
3742
doc(firestore, 'libraries', activeLibraryID, 'users', user.uid)
3843
).data as User;
@@ -56,13 +61,18 @@ const CheckoutRow = ({ checkoutID }: { checkoutID: string }) => {
5661
{checkout?.dueDate?.toDate()?.toDateString() ?? 'Loading'}
5762
</TableCell>
5863
<TableCell>
59-
{checkout.renewsUsed} / {userDoc?.maxRenews ?? 0}
64+
{checkout.renewsUsed} /{' '}
65+
{libraryDoc.checkoutGroups[userDoc.checkoutGroup].maxRenews ?? 0}
6066
<Button
6167
style={{
6268
marginLeft: '1rem',
6369
}}
6470
variant="contained"
65-
disabled={(userDoc?.maxRenews ?? 0) - checkout.renewsUsed <= 0}
71+
disabled={
72+
(libraryDoc.checkoutGroups[userDoc.checkoutGroup].maxRenews ?? 0) -
73+
checkout.renewsUsed <=
74+
0
75+
}
6676
onClick={() => {
6777
httpsCallable(
6878
functions,
@@ -82,7 +92,8 @@ const CheckoutRow = ({ checkoutID }: { checkoutID: string }) => {
8292
});
8393
}}
8494
>
85-
Renew (+7 Days)
95+
Renew (+
96+
{libraryDoc.checkoutGroups[userDoc.checkoutGroup].renewDuration} Days)
8697
</Button>
8798
</TableCell>
8899
<TableCell>

react/src/pages/CheckOut/index.tsx

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ const FindUserTable = ({
9696
const activeLibraryID = useContext(ActiveLibraryID);
9797
if (!activeLibraryID) throw new Error('No active library found!');
9898

99+
const libraryDoc: Library = useFirestoreDocData(
100+
doc(firestore, 'libraries', activeLibraryID)
101+
).data as Library;
102+
99103
const userQueryRef = query(
100104
collection(firestore, 'libraries', activeLibraryID, 'users'),
101105
orderBy(textSearchField),
@@ -141,7 +145,8 @@ const FindUserTable = ({
141145
</TableCell>
142146
<TableCell>{user.email}</TableCell>
143147
<TableCell>
144-
{user.activeCheckouts?.length} / {user.maxCheckouts}
148+
{user.activeCheckouts?.length} /{' '}
149+
{libraryDoc.checkoutGroups[user.checkoutGroup].maxCheckouts}
145150
</TableCell>
146151
</TableRow>
147152
);
@@ -322,6 +327,8 @@ const ScanBooks = ({
322327
const activeLibraryID = useContext(ActiveLibraryID);
323328
if (!activeLibraryID) throw new Error('No active library found!');
324329

330+
if (!checkoutData.user) throw new Error('No user found!');
331+
325332
const firestore = useFirestore();
326333

327334
const activeLibraryDoc: Library = useFirestoreDocData(
@@ -406,7 +413,14 @@ const ScanBooks = ({
406413
id,
407414
parent: parent.id,
408415
parentData,
409-
dueDate: new Date(new Date().setDate(new Date().getDate() + 14))
416+
dueDate: new Date(
417+
new Date().setDate(
418+
new Date().getDate() +
419+
activeLibraryDoc.checkoutGroups[
420+
checkoutData?.user?.checkoutGroup ?? 'default'
421+
].checkoutDuration
422+
)
423+
)
410424
.toISOString()
411425
.split('T')[0],
412426
},
@@ -436,26 +450,29 @@ const ScanBooks = ({
436450
</Form>
437451
)}
438452
</Formik>
439-
{(checkoutData.user?.maxCheckouts ?? 0) -
453+
{(activeLibraryDoc.checkoutGroups[checkoutData.user.checkoutGroup]
454+
.maxCheckouts ?? 0) -
440455
((checkoutData.user?.activeCheckouts.length ?? 0) +
441456
checkoutData.books.length) >=
442457
1 && (
443458
<p>
444459
{checkoutData.user?.firstName} {checkoutData.user?.lastName} is only
445460
allowed{' '}
446-
{(checkoutData.user?.maxCheckouts ?? 0) -
461+
{(activeLibraryDoc.checkoutGroups[checkoutData.user.checkoutGroup]
462+
.maxCheckouts ?? 0) -
447463
((checkoutData.user?.activeCheckouts.length ?? 0) +
448464
checkoutData.books.length)}{' '}
449465
more checkouts.
450466
</p>
451467
)}
452-
{(checkoutData.user?.maxCheckouts ?? 0) -
468+
{(activeLibraryDoc.checkoutGroups[checkoutData.user.checkoutGroup]
469+
.maxCheckouts ?? 0) -
453470
((checkoutData.user?.activeCheckouts.length ?? 0) +
454471
checkoutData.books.length) <
455472
1 && (
456473
<h5>
457474
<b>
458-
{checkoutData.user?.firstName} {checkoutData.user?.lastName} is not
475+
{checkoutData.user?.firstName} {checkoutData.user.lastName} is not
459476
allowed any more checkouts.{' '}
460477
</b>
461478
You can override this.
@@ -729,6 +746,10 @@ const CheckOut = () => {
729746
doc(firestore, 'libraries', activeLibraryID)
730747
).data as Library;
731748

749+
const userDoc: User = useFirestoreDocData(
750+
doc(firestore, 'libraries', activeLibraryID, 'users', user.uid)
751+
).data as User;
752+
732753
const [activeState, setActiveState] = useState(0);
733754
const [checkoutData, setCheckoutData] = useState<checkoutData>({
734755
user: null,
@@ -768,9 +789,17 @@ const CheckOut = () => {
768789
currently checked out
769790
</li>
770791
<li>
771-
Allowed <b>{checkoutData.user?.maxCheckouts ?? 0}</b> checkout
772-
{(checkoutData.user?.maxCheckouts ?? 0) === 1 ? '' : 's'} at a
773-
time
792+
Allowed{' '}
793+
<b>
794+
{libraryDoc.checkoutGroups[userDoc.checkoutGroup]
795+
.maxCheckouts ?? 0}
796+
</b>{' '}
797+
checkout
798+
{(libraryDoc.checkoutGroups[userDoc.checkoutGroup]
799+
.maxCheckouts ?? 0) === 1
800+
? ''
801+
: 's'}{' '}
802+
at a time
774803
</li>
775804
</ul>
776805
</div>

react/src/pages/CheckOuts/CheckoutDialog.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ const CheckoutDialog = () => {
171171
</li>
172172
<br />
173173
<li>
174-
<b>Renews Used:</b> {checkout.renewsUsed} / {user.maxRenews ?? 0}
174+
<b>Renews Used:</b> {checkout.renewsUsed} /{' '}
175+
{libraryDoc.checkoutGroups[user.checkoutGroup].maxRenews}
175176
</li>
176177
</ul>
177178
</div>

0 commit comments

Comments
 (0)