Skip to content

Commit 5cb1a1f

Browse files
Handle Refunds and Stocked/Unstocked Items (#56)
* Refund functional * Properly handle null stock * Fixed listing card styling for mobile
1 parent e0fcc62 commit 5cb1a1f

File tree

10 files changed

+170
-20
lines changed

10 files changed

+170
-20
lines changed

graphql.schema.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,6 +3606,55 @@
36063606
"isDeprecated": false,
36073607
"deprecationReason": null
36083608
},
3609+
{
3610+
"name": "refundPurchase",
3611+
"description": null,
3612+
"args": [
3613+
{
3614+
"name": "course",
3615+
"description": null,
3616+
"type": {
3617+
"kind": "NON_NULL",
3618+
"name": null,
3619+
"ofType": {
3620+
"kind": "SCALAR",
3621+
"name": "String",
3622+
"ofType": null
3623+
}
3624+
},
3625+
"defaultValue": null,
3626+
"isDeprecated": false,
3627+
"deprecationReason": null
3628+
},
3629+
{
3630+
"name": "receiptId",
3631+
"description": null,
3632+
"type": {
3633+
"kind": "NON_NULL",
3634+
"name": null,
3635+
"ofType": {
3636+
"kind": "SCALAR",
3637+
"name": "String",
3638+
"ofType": null
3639+
}
3640+
},
3641+
"defaultValue": null,
3642+
"isDeprecated": false,
3643+
"deprecationReason": null
3644+
}
3645+
],
3646+
"type": {
3647+
"kind": "NON_NULL",
3648+
"name": null,
3649+
"ofType": {
3650+
"kind": "SCALAR",
3651+
"name": "Boolean",
3652+
"ofType": null
3653+
}
3654+
},
3655+
"isDeprecated": false,
3656+
"deprecationReason": null
3657+
},
36093658
{
36103659
"name": "fulfillPurchase",
36113660
"description": null,

src/Components/MarketHome/CreateListingDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export function listingFormToInputType(values: MarketListingFormInput): MarketLi
1818
description: values.description,
1919
image: values.image,
2020
price: parseInt(values.price, 10),
21-
stock: values.stock === '' ? -1 : parseInt(values.stock, 10),
21+
stock: values.stock === '' ? null : Math.max(parseInt(values.stock, 10), 0),
2222
};
2323
}
2424

src/Components/MarketHome/ListingCard.scss

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
}
44

55
.center {
6-
margin: auto;
7-
display: flex;
8-
justify-content: center;
6+
margin: 0;
7+
position: absolute;
8+
top: 50%;
9+
left: 50%;
10+
-ms-transform: translate(-50%, -50%);
11+
transform: translate(-50%, -50%);
912
}
1013

1114
.listing-card-outer {
1215
display: inline-block;
1316
}
1417

15-
1618
.purchase-card {
1719
border: 1px solid rgb(253, 253, 253);
1820
margin-left: 8%;
@@ -33,14 +35,16 @@
3335

3436
.listing-card {
3537
border: 1px solid rgb(255, 255, 255);
36-
margin: 12px;
38+
margin: 0.5em;
3739
box-sizing: border-box;
3840
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3);
3941
border-radius: 8px;
40-
overflow: hidden;
42+
overflow: auto;
4143
background: #fff;
42-
width: 300px;
43-
height: 150px;
44+
min-height: 16em;
45+
height: auto;
46+
min-width: 22em;
47+
width: auto;
4448
display: inline-block;
4549
vertical-align: top;
4650
position: relative;

src/Components/MarketHome/ListingCard.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function ListingCard({
4040

4141
const initialValues: MarketListingFormInput = {
4242
price: listingInfo.price.toString(),
43-
stock: listingInfo.stock ? listingInfo.stock.toString() : '',
43+
stock: listingInfo.stock != null ? listingInfo.stock.toString() : '',
4444
image: listingInfo.image,
4545
description: listingInfo.description,
4646
listingName: listingInfo.listingName,
@@ -112,6 +112,7 @@ export default function ListingCard({
112112
<span>{listingInfo.listingName}</span>
113113
</h3>
114114
<p className="listing-points">{listingInfo.price} P</p>
115+
{listingInfo.stock != null ? <p>{listingInfo.stock} Left</p> : <></>}
115116
</div>
116117
</div>
117118
) : (

src/Components/MarketHome/ListingForm.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ export default function ListingForm({ initialValues, onSubmit, handleClose }: Pr
7878
onBlur={handleBlur}
7979
/>
8080
<SmallTextField
81-
required
8281
id="stock"
8382
label="Stock"
8483
type="number"

src/Components/MarketHome/PurchaseCard.tsx

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
FulfillMutation,
77
ReceiptInfoFragment,
88
useFulfillMutation,
9+
useRefundMutation,
910
} from '../../__generated__/types';
1011
import ReceiptMenu from './SimplyMenu';
1112

@@ -14,6 +15,7 @@ type Props = {
1415
displayStudentName: boolean;
1516
displayListingName: boolean;
1617
editPurchase: any;
18+
deletePurchase: any;
1719
};
1820

1921
function determineMiddleText(displayListingName: boolean, displayStudentName: boolean) {
@@ -31,21 +33,36 @@ export function PurchaseCard({
3133
displayListingName,
3234
displayStudentName,
3335
editPurchase,
36+
deletePurchase,
3437
}: Props) {
3538
const middleText = determineMiddleText(displayListingName, displayStudentName);
3639

37-
const onMutationCompleted = (data: FulfillMutation) => {
40+
const onFulfillCompleted = (data: FulfillMutation) => {
3841
console.log('Mutation Completed');
3942
editPurchase(data.fulfillPurchase);
4043
};
4144

42-
const onMutationError = (e: ApolloError) => {
45+
const onRefundCompleted = () => {
46+
console.log('Mutation Completed');
47+
deletePurchase(purchase.receiptId);
48+
};
49+
50+
const onFulfillError = (e: ApolloError) => {
51+
console.log(e.message);
52+
};
53+
54+
const onRefundError = (e: ApolloError) => {
4355
console.log(e.message);
4456
};
4557

46-
const [fulfill, { loading: mutationLoading }] = useFulfillMutation({
47-
onCompleted: onMutationCompleted,
48-
onError: onMutationError,
58+
const [fulfill, { loading: fulfillLoading }] = useFulfillMutation({
59+
onCompleted: onFulfillCompleted,
60+
onError: onFulfillError,
61+
});
62+
63+
const [refund] = useRefundMutation({
64+
onCompleted: onRefundCompleted,
65+
onError: onRefundError,
4966
});
5067

5168
const onClickFulfill = () => {
@@ -68,9 +85,22 @@ export function PurchaseCard({
6885
}).catch((e) => console.log(e));
6986
};
7087

88+
const onClickRefund = () => {
89+
refund({
90+
variables: {
91+
course: purchase.course,
92+
receiptId: purchase.receiptId,
93+
},
94+
}).catch((e) => console.log(e));
95+
};
96+
7197
return (
7298
<div className="purchase-card">
73-
<ReceiptMenu onClickUnfulfill={onClickUnFulfill} fulfilled={purchase.fulfilled} />
99+
<ReceiptMenu
100+
onClickUnfulfill={onClickUnFulfill}
101+
fulfilled={purchase.fulfilled}
102+
onClickRefund={onClickRefund}
103+
/>
74104
{!purchase.fulfilled ? (
75105
<div>
76106
<Button
@@ -86,7 +116,7 @@ export function PurchaseCard({
86116
onClick={onClickFulfill}
87117
>
88118
<span>Fulfill </span>
89-
{mutationLoading ? <CircularProgress size={15} /> : <></>}
119+
{fulfillLoading ? <CircularProgress size={15} /> : <></>}
90120
</Button>
91121
</div>
92122
) : (

src/Components/MarketHome/PurchaseTab.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ export function PurchaseTab() {
1919
const { classId } = useParams<Record<string, string>>();
2020
const [purchases, setPurchases] = useState<ReceiptInfoFragment[]>([]);
2121

22+
const removeFromPurchases = (receiptId: string) => {
23+
setPurchases(
24+
purchases.filter((p) => {
25+
return p.receiptId !== receiptId;
26+
})
27+
);
28+
};
29+
2230
const { loading, error, data } = useRecentQuery({
2331
variables: {
2432
course: classId,
@@ -58,6 +66,7 @@ export function PurchaseTab() {
5866
{purchases.map((purchase) => {
5967
return (
6068
<PurchaseCard
69+
deletePurchase={removeFromPurchases}
6170
purchase={purchase}
6271
displayListingName
6372
displayStudentName

src/Components/MarketHome/SimplyMenu.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import MoreVertIcon from '@material-ui/icons/MoreVert';
55
type Props = {
66
onClickUnfulfill: any;
77
fulfilled: boolean;
8+
onClickRefund: any;
89
};
910

10-
export default function SimpleMenu({ onClickUnfulfill, fulfilled }: Props) {
11+
export default function SimpleMenu({ onClickUnfulfill, fulfilled, onClickRefund }: Props) {
1112
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
1213

1314
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
@@ -23,6 +24,11 @@ export default function SimpleMenu({ onClickUnfulfill, fulfilled }: Props) {
2324
handleClose();
2425
};
2526

27+
const handleRefund = () => {
28+
onClickRefund();
29+
handleClose();
30+
};
31+
2632
return (
2733
<div>
2834
<Button
@@ -46,7 +52,7 @@ export default function SimpleMenu({ onClickUnfulfill, fulfilled }: Props) {
4652
onClose={handleClose}
4753
>
4854
{fulfilled ? <MenuItem onClick={handleUnfulfill}>Unfulfill</MenuItem> : <></>}
49-
<MenuItem onClick={handleClose}>Refund</MenuItem>
55+
<MenuItem onClick={handleRefund}>Refund</MenuItem>
5056
</Menu>
5157
</div>
5258
);

src/Components/MarketHome/market.graphql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,8 @@ mutation Fulfill($receiptId: String!, $course: String!, $fulfilled: Boolean!) {
9999
...ReceiptInfo
100100
}
101101
}
102+
103+
mutation Refund($receiptId: String!, $course: String!) {
104+
refundPurchase(course: $course, receiptId: $receiptId)
105+
}
106+

src/__generated__/types.ts

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)