Skip to content
This repository was archived by the owner on Dec 25, 2022. It is now read-only.

Commit da81ada

Browse files
committed
Add merge course
1 parent 78f2914 commit da81ada

File tree

7 files changed

+225
-10
lines changed

7 files changed

+225
-10
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "quizlet-learn",
3-
"version": "1.0.12",
3+
"version": "1.0.13",
44
"private": true,
55
"dependencies": {
66
"@nextui-org/react": "^1.0.0-beta.9",

src/App.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import MessageScreen from './screens/MessageScreen';
1212

1313
import ReactGA from 'react-ga4';
1414
import { useEffect } from 'react';
15+
import MergeScreen from './screens/MergeScreen';
1516
ReactGA.initialize('G-FLXKD35453');
1617

1718
function App() {
@@ -40,6 +41,10 @@ function App() {
4041
path={'/learn/pmg/:id'}
4142
element={<LearnPmgScreen title={'Learn PMG course | AdonisGM'} />}
4243
/>
44+
<Route
45+
path={'/merge'}
46+
element={<MergeScreen title={'Merge course | AdonisGM'} />}
47+
/>
4348
</Route>
4449
<Route
4550
path={'/course/:id/exam'}

src/components/Home/Home.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import classes from './Home.module.css';
1717
import { nanoid } from 'nanoid';
1818
import CrawlData from '../CrawlData/CrawlData';
1919
import {
20+
FcCollect,
2021
FcDeleteDatabase,
2122
FcDownload,
2223
FcFile,
@@ -188,6 +189,9 @@ const Home = () => {
188189
case 'crawl':
189190
setShowModalCrawl(true);
190191
break;
192+
case 'merge':
193+
navigate('/merge');
194+
break;
191195
case 'delete':
192196
setIsDeleteMode(!isDeleteMode);
193197
setSelection([]);
@@ -223,6 +227,14 @@ const Home = () => {
223227
>
224228
Import code
225229
</Dropdown.Item>
230+
<Dropdown.Item
231+
key="merge"
232+
description="Merge course for easy learning"
233+
color="success"
234+
icon={<FcCollect />}
235+
>
236+
Merge course
237+
</Dropdown.Item>
226238
</Dropdown.Section>
227239
<Dropdown.Section title="Danger">
228240
<Dropdown.Item
@@ -279,12 +291,13 @@ const Home = () => {
279291
return new Date(b.data.createdAt) - new Date(a.data.createdAt);
280292
})
281293
.map((item) => {
282-
const progress =
283-
(
284-
item.data.data.filter((item) => {
285-
return item.learned;
286-
}).length * 100 / item.data.data.length
287-
).toFixed(2);
294+
const progress = (
295+
(item.data.data.filter((item) => {
296+
return item.learned;
297+
}).length *
298+
100) /
299+
item.data.data.length
300+
).toFixed(2);
288301
return (
289302
<Table.Row key={item.id}>
290303
<Table.Cell>{item.id}</Table.Cell>

src/components/Merge/Merge.js

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import { Button, Card, Grid, Input, Spacer, Text } from '@nextui-org/react';
2+
import { Select } from 'antd';
3+
import { nanoid } from 'nanoid';
4+
import { createRef, useState } from 'react';
5+
import { MdKeyboardBackspace } from 'react-icons/md';
6+
import { useNavigate } from 'react-router-dom';
7+
import classes from './Merge.module.css';
8+
9+
const getAllCourses = () => {
10+
const array = Object.keys(localStorage).map((key) => {
11+
return { id: key, name: JSON.parse(localStorage.getItem(key)).name };
12+
});
13+
return array;
14+
};
15+
16+
const Merge = () => {
17+
const [listCourse, setListCourse] = useState(getAllCourses());
18+
const [first, setFirst] = useState(undefined);
19+
const [second, setSecond] = useState(undefined);
20+
const [name, setName] = useState('');
21+
22+
const navigate = useNavigate();
23+
24+
const handleChangeName = (e) => {
25+
setName(e.target.value.trim());
26+
};
27+
28+
const handlerMerge = () => {
29+
if (first && second && name) {
30+
const firstCourse = JSON.parse(localStorage.getItem(first));
31+
const secondCourse = JSON.parse(localStorage.getItem(second));
32+
const newCourse = {
33+
name,
34+
data: [...firstCourse.data, ...secondCourse.data],
35+
createdAt: new Date().getTime(),
36+
learnedAt: false
37+
};
38+
const id = nanoid(15);
39+
localStorage.setItem(id, JSON.stringify(newCourse));
40+
navigate('/course/' + id);
41+
}
42+
};
43+
44+
return (
45+
<div>
46+
<div>
47+
<Button
48+
auto
49+
color={'default'}
50+
icon={<MdKeyboardBackspace />}
51+
onPress={() => navigate('/')}
52+
>
53+
Back to home
54+
</Button>
55+
</div>
56+
<Spacer y={2} />
57+
<Card>
58+
<Card.Body>
59+
<Grid.Container gap={2}>
60+
<Grid xs={2}></Grid>
61+
<Grid xs={4} direction={'column'}>
62+
<Text p size={14}>
63+
Course 1
64+
</Text>
65+
<Spacer y={0.5} />
66+
<Select
67+
onSelect={(value) => setFirst(value)}
68+
optionFilterProp="children"
69+
filterOption={(input, option) =>
70+
option.children.toLowerCase().includes(input.toLowerCase())
71+
}
72+
filterSort={(optionA, optionB) =>
73+
optionA.children
74+
.toLowerCase()
75+
.localeCompare(optionB.children.toLowerCase())
76+
}
77+
showSearch
78+
className={classes.select}
79+
>
80+
{listCourse
81+
.filter((item) => item.id !== second)
82+
.map((course) => (
83+
<Select.Option key={course.id} value={course.id}>
84+
{course.name}
85+
</Select.Option>
86+
))}
87+
</Select>
88+
</Grid>
89+
<Grid xs={4} direction={'column'}>
90+
<Text p size={14}>
91+
Course 2
92+
</Text>
93+
<Spacer y={0.5} />
94+
<Select
95+
onSelect={(value) => setSecond(value)}
96+
optionFilterProp="children"
97+
filterOption={(input, option) =>
98+
option.children.toLowerCase().includes(input.toLowerCase())
99+
}
100+
filterSort={(optionA, optionB) =>
101+
optionA.children
102+
.toLowerCase()
103+
.localeCompare(optionB.children.toLowerCase())
104+
}
105+
showSearch
106+
className={classes.select}
107+
>
108+
{listCourse
109+
.filter((item) => item.id !== first)
110+
.map((course) => (
111+
<Select.Option key={course.id} value={course.id}>
112+
{course.name}
113+
</Select.Option>
114+
))}
115+
</Select>
116+
</Grid>
117+
<Grid xs={2}></Grid>
118+
</Grid.Container>
119+
<div
120+
style={{
121+
textAlign: 'center',
122+
}}
123+
>
124+
<Spacer y={2} />
125+
<Input
126+
width="400px"
127+
placeholder="New course name"
128+
onChange={handleChangeName}
129+
/>
130+
<Spacer y={1} />
131+
<Button
132+
css={{
133+
width: '140px',
134+
margin: '0 auto',
135+
}}
136+
disabled={
137+
first === undefined || second === undefined || name === ''
138+
}
139+
flat
140+
auto
141+
color={'success'}
142+
onPress={handlerMerge}
143+
>
144+
Merge course
145+
</Button>
146+
</div>
147+
</Card.Body>
148+
</Card>
149+
</div>
150+
);
151+
};
152+
153+
export default Merge;

src/components/Merge/Merge.module.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.select {
2+
width: 100%;
3+
}

src/index.css

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,39 @@ body {
33
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
44
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
55
sans-serif !important;
6-
-webkit-font-smoothing: antialiased;
6+
-webkit-font-smoothing : antialiased;
77
-moz-osx-font-smoothing: grayscale;
8-
background-color: #f6f7fb;
8+
background-color : #f6f7fb;
99
}
1010

1111
code {
1212
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
1313
monospace;
1414
}
1515

16-
@import '~antd/dist/antd.css';
16+
@import '~antd/dist/antd.css';
17+
18+
.ant-input {
19+
border-radius : 10px !important;
20+
padding : 10px !important;
21+
background-color: rgb(244, 245, 247) !important;
22+
border : none !important;
23+
}
24+
25+
.ant-select .ant-select-selector {
26+
padding-top : 4px !important;
27+
padding-bottom: 4px !important;
28+
height : 40px !important;
29+
30+
border-radius : 0.75rem !important;
31+
background-color: #f1f3f5 !important;
32+
color : #11181c !important;
33+
border : none !important;
34+
}
35+
36+
.ant-select-focused .ant-select-selector,
37+
.ant-select-selector:focus,
38+
.ant-select-selector:active,
39+
.ant-select-open .ant-select-selector {
40+
box-shadow: none !important;
41+
}

src/screens/MergeScreen.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { useEffect } from "react"
2+
import Merge from "../components/Merge/Merge"
3+
import ReactGA from 'react-ga4';
4+
5+
const MergeScreen = ({title}) => {
6+
useEffect(() => {
7+
document.title = title
8+
ReactGA.event({ category: 'Merge', action: 'Merge course' });
9+
}, []);
10+
11+
return (
12+
<Merge/>
13+
)
14+
}
15+
16+
export default MergeScreen

0 commit comments

Comments
 (0)