Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c51d7d7

Browse files
committed
assignment-5
1 parent 20a8d3c commit c51d7d7

File tree

8 files changed

+286
-0
lines changed

8 files changed

+286
-0
lines changed

‎assignment-5/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/node_modules

‎assignment-5/README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
## এসাইনমেন্ট রিকুয়ারমেন্ট:
2+
3+
দেখতে দেখতে চলে আসলো আরো একটি এসাইনমেন্ট। এবারের এসাইনমেন্ট আমরা করবো **redux toolkit** এবং **vanilla node js** দিয়ে। এসাইনমেন্ট শুরু করার আগে আপনি যদি পার্ট বাই পার্ট চিন্তা করেন তাহলে দেখবেন এসাইনমেন্ট অনেক সহজ হয়ে গেছে। এই এসাইনমেন্টের জন্যে আপনাকে আমরা একটি API দিয়ে দেবো, সেটি ব্যবহার করে আপনাকে এসাইনমেন্টটি করতে হবে।
4+
5+
#### এসাইনমেন্ট এ আপনাকে যা যা করতে হবেঃ
6+
7+
✓ এই এসাইনমেন্টটি শুধুমাত্র **redux toolkit** দিয়ে করতে হবে। এজন্য যেভাবে এই মডিউলে vanilla node js প্রোজেক্টে **@reduxjs/toolkit** প্যাকেজ install করে প্রোজেক্টটি দেখানো হয়েছে, সেভাবেই আপনারা একটি প্রজেক্ট সেটআপ করে নিবেন। কোনো প্রকার UI based framwork দিয়ে করা যাবে না।
8+
9+
✓ আমাদের দেয়া api থেকে একটি Object আপনাকে async thunk function লিখে fetch করে নিয়ে আসতে হবে। প্রতিটি রিকুয়েস্টে আলাদা আলাদা একটি Object পাবেন।
10+
11+
```
12+
API - http://localhost:9000/videos
13+
```
14+
15+
✓ এই Object এর **tags** নামে একটি প্রোপার্টি আছে যেখানে কিছু tag আছে। এই tag গুলো ব্যবহার করে আরো একটি async thunk dispatch করতে হবে যেটি সার্ভার থেকে search করে রিলেটেড ভিডিও গুলো নিয়ে আসে। যেমনঃ
16+
17+
```
18+
http://localhost:9000/videos?tags_like=javascript&tags_like=react
19+
```
20+
21+
✓ উপরের API থেকে যেই Array of Object পাবেন, সেই Object গুলোর ভেতরে views নামে একটি Property থাকবে, সেই property এর ভিত্তিতে Object গুলো সাজিয়ে Console এ লগ করতে হবে। যেগুলোর ভিউ বেশি থাকবে সেগুলো প্রথমে দেখাবে, এবং সব শেষে কম যেটি সেটি থাকবে।
22+
23+
✓ Console এ লগ করার জন্যে অবশ্যই **redux-logger** এই middleware টি ব্যবহার করতে হবে।
24+
25+
✓ মনে রাখবেন, একবার node application run করে দিলেই দুটি API request sequentially পর পর রান করতে হবে অর্থাৎ প্রথম রিকুয়েস্টে যেই ট্যাগ গুলো পাবো সেই ট্যাগ দিয়ে ‘tags_like’ সার্চ দিয়ে বাকি রিলেটেড ভিডিও গুলো নিয়ে আসতে হবে।
26+
27+
## কিভাবে সাবমিট করবেন:
28+
29+
সবচেয়ে সহজে বুঝার জন্য [এই ভিডিওটি](https://learnwithsumit.com/courses/think-in-a-redux-way/how-to-submit-assignment) দেখে ফেলুন।
30+
31+
এসাইনমেন্টে আপনাকে মাত্র দুইটা জিনিস সাবমিট করতে হবে।
32+
33+
1. **GitHub private repository link:** অবশ্যই সঠিক গিটহাব রিপোজিটরি লিংক দিতে হবে। ভুলে অন্য কোনো লিংক দিলে আপনি এসাইনমেন্টের মার্ক পাবেন না তাই সাবমিট করার আগে নিউ ট্যাবে লিংক ওপেন করে চেক করে নিবেন সঠিক লিংক জমা দিচ্ছেন কিনা।
34+
35+
2. **Live site link:** এই এসাইনমেন্টের ক্ষেত্রে Live site link জমা দিতে হবেনা এবং Netlify তে হোস্ট করতে হবেনা।
36+
37+
**সাবমিট একবারই করতে পারবেন তাই ভালো করে দেখে সাবমিট করবেন।**
38+
39+
## GitHub private repository কিভাবে তৈরি করবেন:
40+
41+
Github Private repositoty তৈরি করতে [এইখানে ক্লিক করুন](https://classroom.github.com/a/4Z7OmZyO) অথবা ব্রাউজারে এই লিংকে **https://classroom.github.com/a/4Z7OmZyO** ভিজিট করুন। লিংকে যাওয়ার পরে **Accept this assignment** এ ক্লিক করুন। সর্বোচ্চ ১মিনিট পরে পেইজটি রিলোড দিলে আপনি আপনার রিপোজেটরি লিংক পেয়ে যাবেন। মনে রাখবেন, আপনাকে এই লিংকটি আমাদের প্লাটফর্মে সাবমিট করতে হবে। না বুঝলে উপরে বলা ভিডিও টিউটোরিয়ালটি দেখে নিন।
42+
43+
## এসাইনমেন্ট মার্কস পলিসি:
44+
45+
আপনি নির্ধারিত সময়ে এসাইনমেন্ট জমা দিলে এবং সব কিছু সঠিকভাবে করলে সম্পূর্ণ মার্ক পাবেন। এর পরে জমা দিলে আপনার মার্ক নিচের নিয়মে কাটা যাবে -
46+
47+
1. ডেডলাইনের পরে এক ঘণ্টার মধ্যে জমা দিলে 10% মার্ক কাটা যাবে।
48+
2. ডেডলাইনের পরে এক ঘণ্টার বেশি কিন্তু 24 ঘণ্টার মধ্যে জমা দিলে 30% মার্ক কাটা যাবে।
49+
3. ডেডলাইনের পরে 24 ঘণ্টার বেশি পরে জমা দিলে 50% মার্ক কাটা যাবে।
50+
4. কোর্স ডিউরেশনের পরে আমরা এসাইনমেন্ট গ্রহণ করবো না।
51+
52+
অবশ্যই কোর্স চলাকালিন সময়ে এসাইনমেন্ট জমা দিতে হবে। কোর্সের ডিউরেশন শেষ হয়ে গেলে তার পরে আপনি এসাইনমেন্টে জমা দিলে এসাইনমেন্টের মার্ক পাবেন না।
53+
54+
## সাবমিট করার পর কোড পরিবর্তন:
55+
56+
আপনি ভেবে নিতে পারেন আপনি ওয়েবসাইটে সঠিক সময়ে এসাইনমেন্ট সাবমিট করে নীরবে পরে গিটহাবে কোড পুশ করতে থাকবেন! আপনার গিটহাবের সর্বশেষ কমিট দেখলেই আমরা বুঝতে পারবো আপনি কখন কোড আপডেট করেছেন। সে অনুযায়ী আমরা আপনার মার্ক কেটে নিবো। তাই এসাইনমেন্ট এর সময় পার হবার পরে আমরা আশা করবো আপনি চালাকি করে আর কোড পুশ করবেন না আপনার রিপোজিটরিতে। এটা করলে আপনার সম্পূর্ণ মার্ক কাটা যেতে পারে।
57+
58+
## এসাইনমেন্ট মার্কস কবে পাবেন:
59+
60+
আমরা সর্বোচ্চ ৭ দিনের ভিতরে এসাইনমেন্টের মার্ক দিয়ে দেওয়ার চেষ্টা করবো। ক্ষেত্র বিশেষে একটু দেরি হতে পারে কারো কারো মার্ক পেতে।

‎assignment-5/index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const store = require("./store");
2+
const { fetchVideo } = require("./videoSlice");
3+
const { fetchRelatedVideos } = require("./relatedVideosSlice");
4+
5+
// subscribe to state changes
6+
store.subscribe(() => {
7+
// console.log(store.getState());
8+
});
9+
10+
// dispatch actions
11+
store
12+
.dispatch(fetchVideo())
13+
.then((action) => {
14+
const firstData = action.payload;
15+
const searchQueryString = firstData?.tags
16+
?.map((tag) => `tags_like=${tag}`)
17+
?.join("&");
18+
19+
// related videos
20+
store.dispatch(fetchRelatedVideos(searchQueryString));
21+
})
22+
.catch((error) => {
23+
console.log("Error occurred while fetching data: ", error);
24+
});

‎assignment-5/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "vanila-redux-toolkit",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"author": "shahnewaz",
6+
"license": "MIT",
7+
"dependencies": {
8+
"@reduxjs/toolkit": "^1.9.3",
9+
"node-fetch": "^2.6.7",
10+
"redux-logger": "^3.0.6"
11+
}
12+
}

‎assignment-5/relatedVideosSlice.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const { createSlice, createAsyncThunk } = require("@reduxjs/toolkit");
2+
const fetch = require("node-fetch");
3+
4+
// initial state
5+
const initialState = { loading: false, videos: [], error: "" };
6+
7+
// create async thunk
8+
const fetchRelatedVideos = createAsyncThunk(
9+
"relatedVideos/fetchRelatedVideos",
10+
async (searchQueryString) => {
11+
const response = await fetch(
12+
`http://localhost:9000/videos?${searchQueryString}`
13+
);
14+
const relatedVideos = await response.json();
15+
16+
const sortedVideos = relatedVideos?.sort((a, b) =>
17+
parseFloat(a?.views) > parseFloat(b?.views) ? -1 : 1
18+
);
19+
20+
return sortedVideos;
21+
}
22+
);
23+
24+
const relatedVideosSlice = createSlice({
25+
name: "relatedVideos",
26+
initialState,
27+
extraReducers: (builder) => {
28+
builder.addCase(fetchRelatedVideos.pending, (state, action) => {
29+
state.loading = true;
30+
state.error = "";
31+
});
32+
33+
builder.addCase(fetchRelatedVideos.fulfilled, (state, action) => {
34+
state.loading = false;
35+
state.error = "";
36+
state.videos = action.payload;
37+
});
38+
39+
builder.addCase(fetchRelatedVideos.rejected, (state, action) => {
40+
state.loading = false;
41+
state.error = action.error?.message;
42+
state.videos = [];
43+
});
44+
},
45+
});
46+
47+
module.exports = relatedVideosSlice.reducer;
48+
module.exports.fetchRelatedVideos = fetchRelatedVideos;

‎assignment-5/store.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const { configureStore } = require("@reduxjs/toolkit");
2+
const { createLogger } = require("redux-logger");
3+
const videoReducer = require("./videoSlice");
4+
const relatedReducer = require("./relatedVideosSlice");
5+
6+
// logger
7+
const logger = createLogger();
8+
9+
// configure store
10+
const store = configureStore({
11+
reducer: {
12+
video: videoReducer,
13+
relatedVideos: relatedReducer,
14+
},
15+
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
16+
});
17+
18+
module.exports = store;

‎assignment-5/videoSlice.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const { createSlice, createAsyncThunk } = require("@reduxjs/toolkit");
2+
const fetch = require("node-fetch");
3+
4+
// initial state
5+
const initialState = { loading: false, video: {}, error: "" };
6+
7+
// create async thunk
8+
const fetchVideo = createAsyncThunk("video/fetchVideo", async () => {
9+
const response = await fetch("http://localhost:9000/videos");
10+
const video = await response.json();
11+
12+
return video;
13+
});
14+
15+
const videoSlice = createSlice({
16+
name: "video",
17+
initialState,
18+
extraReducers: (builder) => {
19+
builder.addCase(fetchVideo.pending, (state, action) => {
20+
state.loading = true;
21+
state.error = "";
22+
});
23+
24+
builder.addCase(fetchVideo.fulfilled, (state, action) => {
25+
state.loading = false;
26+
state.error = "";
27+
state.video = action.payload;
28+
});
29+
30+
builder.addCase(fetchVideo.rejected, (state, action) => {
31+
state.loading = false;
32+
state.error = action.error?.message;
33+
state.video = {};
34+
});
35+
},
36+
});
37+
38+
module.exports = videoSlice.reducer;
39+
module.exports.fetchVideo = fetchVideo;

‎assignment-5/yarn.lock

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
# yarn lockfile v1
3+
4+
5+
"@babel/runtime@^7.9.2":
6+
version "7.21.0"
7+
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
8+
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
9+
dependencies:
10+
regenerator-runtime "^0.13.11"
11+
12+
"@reduxjs/toolkit@^1.9.3":
13+
version "1.9.3"
14+
resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.9.3.tgz#27e1a33072b5a312e4f7fa19247fec160bbb2df9"
15+
integrity sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==
16+
dependencies:
17+
immer "^9.0.16"
18+
redux "^4.2.0"
19+
redux-thunk "^2.4.2"
20+
reselect "^4.1.7"
21+
22+
deep-diff@^0.3.5:
23+
version "0.3.8"
24+
resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84"
25+
integrity sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==
26+
27+
immer@^9.0.16:
28+
version "9.0.19"
29+
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.19.tgz#67fb97310555690b5f9cd8380d38fc0aabb6b38b"
30+
integrity sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==
31+
32+
node-fetch@^2.6.7:
33+
version "2.6.9"
34+
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6"
35+
integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==
36+
dependencies:
37+
whatwg-url "^5.0.0"
38+
39+
redux-logger@^3.0.6:
40+
version "3.0.6"
41+
resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
42+
integrity sha512-JoCIok7bg/XpqA1JqCqXFypuqBbQzGQySrhFzewB7ThcnysTO30l4VCst86AuB9T9tuT03MAA56Jw2PNhRSNCg==
43+
dependencies:
44+
deep-diff "^0.3.5"
45+
46+
redux-thunk@^2.4.2:
47+
version "2.4.2"
48+
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b"
49+
integrity sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==
50+
51+
redux@^4.2.0:
52+
version "4.2.1"
53+
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
54+
integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
55+
dependencies:
56+
"@babel/runtime" "^7.9.2"
57+
58+
regenerator-runtime@^0.13.11:
59+
version "0.13.11"
60+
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
61+
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
62+
63+
reselect@^4.1.7:
64+
version "4.1.7"
65+
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.7.tgz#56480d9ff3d3188970ee2b76527bd94a95567a42"
66+
integrity sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==
67+
68+
tr46@~0.0.3:
69+
version "0.0.3"
70+
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
71+
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
72+
73+
webidl-conversions@^3.0.0:
74+
version "3.0.1"
75+
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
76+
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
77+
78+
whatwg-url@^5.0.0:
79+
version "5.0.0"
80+
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
81+
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
82+
dependencies:
83+
tr46 "~0.0.3"
84+
webidl-conversions "^3.0.0"

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /