Skip to content

Commit 9c2b495

Browse files
Student purchasing (#57)
* Rediret on role, Student home page account balance * Listin card styling * More listing card styling * Change purchase button depending on purchase eligibility * Purchasing functional * Refetch all on successful purchase * Fixed eslint warnings * Fixed uncaught eslint warning * Fixed another eslint warning
1 parent 5cb1a1f commit 9c2b495

File tree

13 files changed

+463
-43
lines changed

13 files changed

+463
-43
lines changed

graphql.schema.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4994,9 +4994,13 @@
49944994
"description": null,
49954995
"args": [],
49964996
"type": {
4997-
"kind": "OBJECT",
4998-
"name": "User",
4999-
"ofType": null
4997+
"kind": "NON_NULL",
4998+
"name": null,
4999+
"ofType": {
5000+
"kind": "OBJECT",
5001+
"name": "User",
5002+
"ofType": null
5003+
}
50005004
},
50015005
"isDeprecated": false,
50025006
"deprecationReason": null

public/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"short_name": "React App",
3-
"name": "Create React App Sample",
2+
"short_name": "Market",
3+
"name": "Flipt(ed) Marketplace",
44
"icons": [
55
{
66
"src": "favicon.ico",

src/Components/Content/Content.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
11
import { Switch, Route } from 'react-router-dom';
22
import Dashboard from '../Dashboard/Dashboard';
33
import './Content.css';
4-
import MarketHome from '../MarketHome/MarketHome';
5-
import { CourseInfoFieldsFragment } from '../../__generated__/types';
4+
import MarketHomeInstructor from '../MarketHome/MarketHome';
5+
import { CourseInfoFieldsFragment, Role, useUserQuery } from '../../__generated__/types';
66
import { Settings } from '../Settings/Settings';
7+
import { MarketHomeStudent } from '../MarketHome/Student/MarketHomeStudent';
78

89
type Props = {
910
courses: CourseInfoFieldsFragment[];
1011
refetchCourses: any;
1112
};
1213

1314
export default function Content({ courses, refetchCourses }: Props) {
15+
const { loading, error, data } = useUserQuery();
16+
17+
if (loading || error || !data) {
18+
return <></>;
19+
}
20+
21+
const { getUser } = data;
22+
1423
return (
1524
<div className="content">
1625
<Switch>
1726
<Route path="/courseHome/:classId/:className">
18-
<MarketHome />
27+
{getUser.role === Role.Instructor ? <MarketHomeInstructor /> : <MarketHomeStudent />}
1928
</Route>
2029
<Route path="/settings">
21-
<Settings />
30+
<Settings user={getUser} />
2231
</Route>
2332
<Route path="/">
24-
<Dashboard courses={courses} refetchCourses={refetchCourses} />
33+
<Dashboard courses={courses} refetchCourses={refetchCourses} role={getUser.role} />
2534
</Route>
2635

2736
{/* <Route path="/taskSubmissionOverview">

src/Components/Dashboard/Dashboard.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
import { CourseInfoFieldsFragment } from '../../__generated__/types';
1+
import { CourseInfoFieldsFragment, Role } from '../../__generated__/types';
22
import CourseCard from './CourseCard';
33
import CreateCourseDialog from '../CreateCourseDialog/CreateCourseDialog';
44
import './DashBoard.css';
55

66
type Props = {
77
courses: CourseInfoFieldsFragment[];
88
refetchCourses: any;
9+
role: Role;
910
};
1011

11-
function Dashboard({ courses, refetchCourses }: Props) {
12+
function Dashboard({ courses, refetchCourses, role }: Props) {
1213
return (
1314
<div>
14-
<CreateCourseDialog refetch={refetchCourses} />
15+
{role === Role.Instructor ? <CreateCourseDialog refetch={refetchCourses} /> : <></>}
1516
{courses.map((courseInfo: CourseInfoFieldsFragment) => (
1617
<CourseCard key={courseInfo.courseId} courseInfo={courseInfo} />
1718
))}

src/Components/MarketHome/ListingCard.scss

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,61 @@
22
margin-left: 18px;
33
}
44

5+
.student-market-home {
6+
background-color: #e3f2fd !important;
7+
.student-welcome {
8+
margin-left: 0.6em;
9+
color: #4274f3;
10+
display: flex;
11+
justify-content: left;
12+
width: 75%;
13+
}
14+
15+
.student-listing-header {
16+
display: flex;
17+
justify-content: center;
18+
color: #4274f3;
19+
font-size: 36px;
20+
font-weight: 600;
21+
margin-bottom: 0px;
22+
}
23+
24+
.line {
25+
margin-top: 0px;
26+
border-top: 4px solid #4274f3;
27+
color: #4274f3;
28+
width: 90%;
29+
border-radius: 12px;
30+
}
31+
}
32+
33+
.student-balance {
34+
font-size: 5em;
35+
font-weight: bolder;
36+
}
37+
38+
.account-card-contents {
39+
margin: 1em;
40+
.account-card-header {
41+
font-weight: 600;
42+
font-size: 25px;
43+
}
44+
}
45+
46+
.account-card {
47+
border: 1px solid #4274f3;
48+
margin: 1.5em;
49+
box-sizing: border-box;
50+
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3);
51+
border-radius: 12px;
52+
overflow: auto;
53+
background: #4274f3;
54+
min-height: 11em;
55+
height: auto;
56+
position: relative;
57+
color: white;
58+
}
59+
560
.center {
661
margin: 0;
762
position: absolute;
@@ -13,6 +68,9 @@
1368

1469
.listing-card-outer {
1570
display: inline-block;
71+
justify-content: center;
72+
align-content: center;
73+
text-align: center;
1674
}
1775

1876
.purchase-card {
@@ -33,25 +91,26 @@
3391
position: relative;
3492
}
3593

94+
.purchase-popup {
95+
display: inline-block
96+
}
97+
3698
.listing-card {
3799
border: 1px solid rgb(255, 255, 255);
38100
margin: 0.5em;
39101
box-sizing: border-box;
40-
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3);
102+
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.3);
41103
border-radius: 8px;
42104
overflow: auto;
43105
background: #fff;
44-
min-height: 16em;
106+
min-height: 218px;
45107
height: auto;
46-
min-width: 22em;
108+
min-width: 336px;
47109
width: auto;
48110
display: inline-block;
49111
vertical-align: top;
50-
position: relative;
51-
}
52112

53-
.listing-card-details {
54-
margin-top: 1em;
113+
position: relative;
55114
}
56115

57116
.listing-card {
@@ -75,19 +134,28 @@
75134

76135
.listing-card-body {
77136
float: right;
78-
width: 55%;
137+
width: 70%;
79138
padding-top: 10%;
80-
padding-right: 9%;
139+
font-family: sans-serif;
81140
.listing-title {
82141
font-size: 1.4em;
83142
color: black;
84143
display: inline-flex;
85144
align-content: center;
145+
font-weight: 700;
86146
}
87147
.listing-points {
88148
color: rgb(0, 0, 0);
89-
font-size: 1.5em;
90-
font-weight: bold;
149+
font-size: 1.8em;
150+
font-weight: 800;
151+
}
152+
.listing-stock {
153+
margin-top: 0.5em;
154+
font-size: 1.2em;
155+
font-weight: 700;
156+
}
157+
.listing-card-button {
158+
color: #2f80ed;
91159
}
92160
}
93161
}

src/Components/MarketHome/ListingTab.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { ListingFieldsFragment, useMarketListingsQuery } from '../../__generated
55
import CreateListingDialog from './CreateListingDialog';
66
import ListingCard from './ListingCard';
77

8-
const sortListings = (a: ListingFieldsFragment, b: ListingFieldsFragment) => {
8+
export const sortListings = (a: ListingFieldsFragment, b: ListingFieldsFragment) => {
99
return a.listingName.localeCompare(b.listingName);
1010
};
1111

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { useParams } from 'react-router-dom';
2+
import ShoppingCartIcon from '@material-ui/icons/ShoppingCartOutlined';
3+
import { CircularProgress } from '@material-ui/core';
4+
import { useEffect, useState } from 'react';
5+
import {
6+
ListingFieldsFragment,
7+
useMarketListingsQuery,
8+
useStudentInfoQuery,
9+
} from '../../../__generated__/types';
10+
import { sortListings } from '../ListingTab';
11+
import { StudentListingCard } from './StudentListingCard';
12+
13+
export function MarketHomeStudent() {
14+
const { classId, className } = useParams<Record<string, string>>();
15+
const [, setListings] = useState<ListingFieldsFragment[]>([]);
16+
17+
const {
18+
loading: studentLoading,
19+
data: studentData,
20+
refetch: refetchStudent,
21+
} = useStudentInfoQuery({
22+
variables: {
23+
courseId: classId,
24+
},
25+
});
26+
27+
const {
28+
loading: listingLoading,
29+
data: listingData,
30+
refetch: refetchListings,
31+
} = useMarketListingsQuery({
32+
variables: {
33+
courseId: classId,
34+
},
35+
});
36+
37+
const refetchAll = () => {
38+
refetchStudent().catch((e) => console.log(e));
39+
refetchListings().catch((e) => console.log(e));
40+
};
41+
42+
useEffect(() => {
43+
if (!listingData || !studentData) {
44+
return;
45+
}
46+
setListings([...listingData.marketListings].sort(sortListings));
47+
}, [listingData, studentData]);
48+
49+
if (!studentData || studentLoading) {
50+
return <></>;
51+
}
52+
const { student } = studentData;
53+
54+
return (
55+
<div className="student-market-home">
56+
{studentData ? (
57+
<div>
58+
<h2 className="student-welcome">
59+
Hello {studentData.student.firstName}! Welcome to your {className} account.
60+
</h2>
61+
<div className="account-card">
62+
<div className="account-card-contents">
63+
<h5 className="account-card-header">Account Balance</h5>
64+
<h3 className="student-balance">${studentData.student.points} EXP</h3>
65+
</div>
66+
</div>
67+
<div className="student-listing-header">
68+
<ShoppingCartIcon style={{ fontSize: 48 }} />
69+
<span> Marketplace</span>
70+
</div>
71+
<hr className="line" />
72+
</div>
73+
) : (
74+
<></>
75+
)}
76+
<div className="listing-card-outer">
77+
{listingLoading || !listingData ? (
78+
<div className="center">
79+
<CircularProgress size={150} />
80+
</div>
81+
) : (
82+
listingData.marketListings.map((listing: ListingFieldsFragment) => {
83+
return (
84+
<StudentListingCard
85+
refetch={refetchAll}
86+
listingInfo={listing}
87+
studentBalance={student.points}
88+
/>
89+
);
90+
})
91+
)}
92+
</div>
93+
</div>
94+
);
95+
}

0 commit comments

Comments
 (0)