68 |
Subscribe to Manohar Batra YT Channel
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | setSearchTerm(e.target.value)}
83 | className="search-input"
84 | />
85 |
86 |
87 | {categories.map((category) => (
88 |
98 | ))}
99 |
100 | {selectedCategory && playlists && (
101 |
102 | {playlists.map((playlist) => (
103 | setSelectedPlaylist(playlist === "All" ? 'All' : playlist)}
107 | >
108 | {playlist}
109 | openModalPlaylist(playlist)}>
110 | Notes
111 |
112 |
113 | ))}
114 |
115 | )}
116 |
117 | {filteredVideos.map((video, index) => (
118 |
119 | {/*
*/}
127 |
137 |
{video.title}
138 |
139 | ))}
140 |
141 |
142 |
143 | );
144 | };
145 |
146 | export default App;
147 |
--------------------------------------------------------------------------------
/currency-converter/src/pages/currencyConverter/css/currencyConverter.css:
--------------------------------------------------------------------------------
1 | body{
2 | /* background-image: url('../../../assets/images/bg-image.jpg'); */
3 | /* background-color: #fff; */
4 | }
5 |
6 | .headerContent{
7 | min-height: 270px;
8 | width: auto;
9 | background-color: #1746A2;
10 | padding-top: 5rem;
11 | position: relative;
12 | }
13 | .headerTitle{
14 | color: #EEF1FF;
15 | position: absolute;
16 | left: 0;
17 | right: 0;
18 | z-index: 0;
19 | bottom: 90px;
20 | }
21 |
22 | .currency-container{
23 | margin-top: -70px;
24 | /* background-color: #EEF1FF; */
25 | background-color: #FFF;
26 | /* padding: 50px 30px; */
27 | padding: 45px;
28 | border-radius: 10px;
29 | box-shadow: rgb(35 55 80 / 30%) 0px 6px 12px;
30 | z-index: 9999;
31 | }
32 | .inputAmount{
33 | padding: 5px 10px;
34 | font-weight: bold;
35 | border: none;
36 | border-bottom: 3px solid #ccc;
37 | width: 100%;
38 | height: 40px !important;
39 | padding-left: 0;
40 | }
41 | .css-13cymwt-control, .css-t3ipsp-control{
42 | border: none !important;
43 | border-bottom: 3px solid #ccc !important;
44 | border-radius: 0 !important;
45 | height: 40px !important;
46 | max-height: 40px !important;
47 | }
48 | .css-t3ipsp-control{
49 | box-shadow: none !important;
50 | }
51 | .swap-icon {
52 | /* background: #675AFE; */
53 | height: 37px;
54 | max-height: 37px;
55 | border: 3px solid #1746a2;
56 | padding: 5px;
57 | border-radius: 50%;
58 | width: 37px;
59 | max-width: 37px;
60 | text-align: center;
61 | color: #1746a2;
62 | cursor: pointer;
63 | }
64 | .font-weight-bold{font-weight: bold;}
65 | .mb-10{margin-bottom: 10px;}
66 | .pl-0{padding-left: 0;}
67 | .text-right{
68 | text-align: right;
69 | }
70 | input:focus-visible, select:focus-visible {
71 | outline: none;
72 | /* border-radius: 3px; */
73 | }
74 | .currency-symbol{
75 | border-bottom: 3px solid #ccc;
76 | height: 40px !important;
77 | width: 100%;
78 | text-align: center;
79 | display: flex;
80 | justify-content: center;
81 | align-items: center;
82 | }
83 | .lbl-title{
84 | color: #1746a2 ;
85 | }
86 | .btn-convert{
87 | border-color: #1746a2;
88 | border-radius: 0;
89 | border-width: 3px;
90 | font-weight: bold;
91 | color: #1746a2;
92 | }
93 |
94 | .btn-convert:hover, .btn-convert:active{
95 | border-color: #0d6efd;
96 | color: #0d6efd !important;
97 | border-radius: 2px;
98 | background-color: #fff !important;
99 | }
100 | .font-awes-icon{
101 | color: #5c667bb5;
102 | font-size: 25px;
103 | }
104 | .disclaimer-container{
105 | background-color: #f2f7fe;
106 | color: #5c667b;
107 | border-radius: 8px;
108 | padding: 15px 10px;
109 | }
110 | .disclaimer-text-container {
111 | font-size: 12px;
112 | }
113 | .result-currency-from {
114 | color: #5c667b;
115 | font-weight: bold;
116 | font-size: 1.2rem;
117 | }
118 | .result-currency-to {
119 | color: #1746a2;
120 | font-weight: bold;
121 | font-size: 1.8rem;
122 | }
123 | .exchange-rate {
124 | font-size: 0.9rem !important;
125 | text-decoration: underline;
126 | color: #5c667b;
127 | text-underline-offset: 5px;
128 | }
129 | .result-container {
130 | transition: all .5s;
131 | height: 80px;
132 | }
133 | .hidden{
134 | height: 0px !important;
135 | transition: all .5s;
136 | }
137 | #loader {
138 | z-index: 99999;
139 | translate: 0 10px;
140 | position: absolute;
141 | }
142 |
143 | .blur-2{
144 | filter: blur(2px);
145 | }
146 | .page-currecy-converter{
147 | /* display: flex;
148 | align-items: center;
149 | justify-content: center;
150 | min-height: 100vh;
151 | padding: 0 10px; */
152 | /* background: #675AFE; */
153 | }
154 | /* ::selection{
155 | color: #fff;
156 | background: #675AFE;
157 | }
158 | .wrapper{
159 | width: 470px;
160 | padding: 30px;
161 | border-radius: 7px;
162 | background: #fff;
163 | box-shadow: 7px 7px 20px rgba(0, 0, 0, 0.05);
164 | margin: 0 auto;
165 | }
166 | .wrapper header{
167 | font-size: 28px;
168 | font-weight: 500;
169 | text-align: center;
170 | }
171 | .wrapper form{
172 | margin: 40px 0 20px 0;
173 | }
174 | form :where(input, select, button){
175 | width: 100%;
176 | outline: none;
177 | border-radius: 5px;
178 | border: none;
179 | }
180 | form p{
181 | font-size: 18px;
182 | margin-bottom: 5px;
183 | }
184 | form input{
185 | height: 50px;
186 | font-size: 17px;
187 | padding: 0 15px;
188 | border: 1px solid #999;
189 | }
190 | form input:focus{
191 | padding: 0 14px;
192 | border: 2px solid #675AFE;
193 | } */
194 | /*
195 | form .drop-list{
196 | display: flex;
197 | margin-top: 20px;
198 | align-items: center;
199 | justify-content: space-between;
200 | }
201 | .drop-list .select-box{
202 | display: flex;
203 | width: 115px;
204 | height: 45px;
205 | align-items: center;
206 | border-radius: 5px;
207 | justify-content: center;
208 | border: 1px solid #999;
209 | }
210 | .select-box img{
211 | max-width: 21px;
212 | }
213 | .select-box select{
214 | width: auto;
215 | font-size: 16px;
216 | background: none;
217 | margin: 0 -5px 0 5px;
218 | }
219 | .select-box select::-webkit-scrollbar{
220 | width: 8px;
221 | }
222 | .select-box select::-webkit-scrollbar-track{
223 | background: #fff;
224 | }
225 | .select-box select::-webkit-scrollbar-thumb{
226 | background: #888;
227 | border-radius: 8px;
228 | border-right: 2px solid #ffffff;
229 | }
230 | .drop-list .icon{
231 | cursor: pointer;
232 | margin-top: 30px;
233 | font-size: 22px;
234 | } */
235 | /* form .exchange-rate{
236 | font-size: 17px;
237 | margin: 20px 0 30px;
238 | }
239 | form button{
240 | height: 52px;
241 | color: #fff;
242 | font-size: 17px;
243 | cursor: pointer;
244 | background: #675AFE;
245 | transition: 0.3s ease;
246 | }
247 | form button:hover{
248 | background: #4534fe;
249 | } */
250 |
251 | #swap-icon{
252 | /* color: #4534fe;
253 | font-size: 17px;
254 | cursor: pointer;
255 | transition: 0.3s ease;
256 | display: inline-block;
257 | padding: 5px;
258 | border-radius: 4px; */
259 | /* background: #675AFE; */
260 | /* height: 52px; */
261 | }
262 | /* #swap-icon:hover{
263 | background: #4534fe;
264 | } */
--------------------------------------------------------------------------------
/image-gallery-dnd/src/App.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | DndContext,
3 | DragOverlay,
4 | MouseSensor,
5 | TouchSensor,
6 | closestCenter,
7 | useSensor,
8 | useSensors,
9 | } from "@dnd-kit/core";
10 | import {
11 | SortableContext,
12 | arrayMove,
13 | rectSortingStrategy,
14 | } from "@dnd-kit/sortable";
15 | import axios from "axios";
16 | import { useEffect, useState } from "react";
17 | import "./App.css";
18 |
19 | import ImageCard from "./Components/ImageCard";
20 | import OverlayImage from "./Components/OverlayImage";
21 | import Loader from "./Components/Loader";
22 | import ImageUploader from "./Components/ImageUploader";
23 | import { Analytics } from '@vercel/analytics/react';
24 |
25 |
26 | function App() {
27 | const [images, setImages] = useState([]);
28 | const [image, setImage] = useState(null);
29 | const [activeImage, setActiveImage] = useState(null);
30 | const [totalChecked, setTotalChecked] = useState(0);
31 |
32 | useEffect(() => {
33 | axios
34 | .get("https://nest-image-gallery.vercel.app/api/v1/image/all")
35 | .then(function (response) {
36 | const imageData = response.data.map((image) => {
37 | const newImage = { ...image, id: image._id, isChecked: false };
38 | return newImage;
39 | });
40 | setImages(imageData);
41 | })
42 | .catch(function (error) {
43 | console.log(error);
44 | });
45 | }, []);
46 |
47 | const sensors = useSensors(
48 | useSensor(MouseSensor, {
49 | activationConstraint: {
50 | distance: 8,
51 | },
52 | }),
53 | useSensor(TouchSensor, {
54 | activationConstraint: {
55 | distance: 8,
56 | },
57 | })
58 | );
59 |
60 | //to handle bulk unselect
61 | const handleUnChecked = () => {
62 | const uncheckedImages = images.map((img) => {
63 | return { ...img, isChecked: false };
64 | });
65 | setImages(uncheckedImages);
66 |
67 | setTotalChecked(0);
68 | };
69 |
70 | //to handle individual select
71 | const checked = (index) => {
72 | const updatedImages = [...images];
73 | updatedImages[index].isChecked = !updatedImages[index].isChecked;
74 | setImages(updatedImages);
75 |
76 | setTotalChecked(images.filter((image) => image.isChecked).length ?? 0);
77 | };
78 |
79 | //to handle delete
80 | const handleDelete = () => {
81 | const deletingIds = [];
82 | images.forEach((image) => {
83 | if (image.isChecked) {
84 | deletingIds.push(image.id);
85 | }
86 | });
87 |
88 | const deletingIdsStr = deletingIds.map((id) => `ids=${id}`).join("&");
89 |
90 | axios
91 | .delete(
92 | `https://nest-image-gallery.vercel.app/api/v1/image/delete-multiple?${deletingIdsStr}`
93 | )
94 | .then(function (response) {
95 | if (response.data.isDeleted) {
96 | const remainingImages = images.filter(
97 | (image) => !deletingIds.includes(image.id)
98 | );
99 | setImages(remainingImages);
100 | }
101 | })
102 | .catch(function (error) {
103 | console.log(error);
104 | });
105 | setTotalChecked(0);
106 | };
107 |
108 | const handleDragStart = (event) => {
109 | const active = images.find((image) => image.id === event.active.id);
110 | setActiveImage(active.url);
111 | };
112 |
113 | const handleDragCancel = () => {
114 | setActiveImage(null);
115 | };
116 |
117 | //to handle dnd kit OnDragEnd
118 | const onDragEnd = (event) => {
119 | const { active, over } = event;
120 | if (active.id === over.id) {
121 | return;
122 | }
123 | setImages((images) => {
124 | const oldIndex = images.findIndex((image) => image.id === active.id);
125 | const newIndex = images.findIndex((image) => image.id === over.id);
126 | return arrayMove(images, oldIndex, newIndex);
127 | });
128 | };
129 |
130 | // setTotalChecked(images.filter((image) => image.isChecked).length ?? 0);
131 |
132 | //Separate imageCard for dnd kit with dnd kit function and props
133 |
134 | const handleFileChange = (e) => {
135 | const form = new FormData();
136 |
137 | const file = e.target.files[0];
138 | setImage(URL.createObjectURL(file));
139 |
140 | form.append("image", file);
141 |
142 | axios
143 | .post(
144 | "https://api.imgbb.com/1/upload?key=4389f6aa038004767b479af56fd374b6",
145 | form
146 | )
147 | .then(function (response) {
148 | createNewEntry({
149 | imgBBId: response.data.data.id,
150 | fileName: response.data.data.image.filename,
151 | url: response.data.data.image.url,
152 | });
153 | })
154 | .catch(function (error) {
155 | console.log(error);
156 | });
157 | };
158 |
159 | const createNewEntry = (body) => {
160 | axios
161 | .post("https://nest-image-gallery.vercel.app/api/v1/image/create", body)
162 | .then(function (response) {
163 | setImages([
164 | ...images,
165 | { ...response.data, id: response.data._id, isChecked: false },
166 | ]);
167 | })
168 | .catch(function (error) {
169 | console.log(error);
170 | });
171 | setImage(null);
172 | };
173 |
174 | return (
175 | <>
176 |
212 |
213 | {/* checking if any image selected, if selected then delete button will appear */}
214 | {totalChecked ? (
215 |
216 |
217 | handleUnChecked()}
221 | defaultChecked={totalChecked > 0 ? true : false}
222 | />
223 |
224 | {totalChecked} Images Selected
225 |
226 |
227 |
228 |
232 |
246 | Delete
247 |
248 |
249 | ) : (
250 |
251 | Image Gallery
252 |
253 | )}
254 |
255 | {/* dnd kit component */}
256 |
261 |
262 |
263 | {/* checking if any image available or not */}
264 | {images?.length > 0 ? (
265 | images.map((elm, index) => (
266 |
267 | ))
268 | ) : (
269 |
No Images
270 | )}
271 | {/*

*/}
272 |
273 |
287 |
288 | {/*
Upload Images
*/}
289 |
292 |
300 |
301 |
302 |
303 |
304 |
305 | >
306 | );
307 | }
308 |
309 | export default App;
310 |
--------------------------------------------------------------------------------
/currency-converter/src/pages/currencyConverter/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { useState, useEffect, useMemo } from "react";
4 | import './css/currencyConverter.css';
5 | import currencies from '../../utils/seeds/commonCurrency.json';
6 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
7 | import FadeLoader from "react-spinners/FadeLoader";
8 | import Select from 'react-select'
9 | import CurrencyInput from 'react-currency-input-field';
10 |
11 | import {
12 | faSyncAlt, faRepeat, faRightLeft, faCircleInfo
13 | } from "@fortawesome/free-solid-svg-icons";
14 |
15 | const URL = `https://v6.exchangerate-api.com/v6/${process.env.REACT_APP_EXCHANGE_RATE_API_KEY}/pair`;
16 |
17 | function currencyConverter(props) {
18 | const [exchangeRate, setExchangeRate] = useState(0);
19 | const [exchangeRateAmount, setExchangeRateAmount] = useState(0);
20 | const [selectedCurrencySymbol, setSelectedCurrencySymbol] = useState("$");
21 | const [selectAmount, setSelectAmount] = useState(10);
22 | const [exchangedSelectAmount, setExchangedSelectAmount] = useState(1);
23 | const [date, setDate] = useState(new Date());
24 | const [isLoading, setLoading] = useState(false);
25 | const [reslultContaierCls, setReslultContaierCls] = useState("hidden");
26 |
27 |
28 | let cuntriesOptions = [];
29 | Object.keys(currencies).map((currency, index) => {
30 | cuntriesOptions.push({
31 | value: currencies[currency].code,
32 | label: `${currencies[currency].code} - ${currencies[currency].name}`,
33 | name: currencies[currency].name,
34 | symbol: currencies[currency].symbol,
35 | index: index
36 | })
37 | });
38 |
39 | const [selectedCurrencyFrom, setSelectedCurrencyFrom] = useState(cuntriesOptions[0]);
40 | const [selectedCurrencyTo, setSelectedCurrencyTo] = useState(cuntriesOptions[48]);
41 |
42 | useEffect(() => {
43 | if( selectAmount ){
44 | handleConvert();
45 | }
46 | }, [selectedCurrencyFrom, selectedCurrencyTo]);
47 |
48 | const handleConvert = () => {
49 | setLoading(true);
50 | setExchangeRateAmount(0);
51 | setExchangeRate(0)
52 | setReslultContaierCls('hidden');
53 |
54 | const controller = new AbortController();
55 | const signal = controller.signal;
56 | fetch(`${URL}/${selectedCurrencyFrom.value}/${selectedCurrencyTo.value}/${selectAmount}`, { signal })
57 | .then((res) => res.json())
58 | .then((data) => {
59 | console.log({ data });
60 | if (data.result === "success") {
61 | var conversionRate = data.conversion_rate
62 | setExchangedSelectAmount(selectAmount);
63 | setExchangeRateAmount(roundOffToX(2, data.conversion_result));
64 | setExchangeRate(roundOffToX(2, conversionRate))
65 | setLoading(false);
66 | setReslultContaierCls('');
67 | }
68 |
69 | }).catch(err => {
70 | setLoading(false);
71 | });
72 | return () => {
73 | controller.abort();
74 | }
75 |
76 |
77 | }
78 |
79 | useEffect(() => {
80 |
81 | const inerval = setInterval(() => {
82 | setDate(new Date());
83 | }, 1000);
84 |
85 | return () => {
86 | clearInterval(inerval);
87 | }
88 | }, []);
89 |
90 | const handleSelectTo = (_eTo) => {
91 | setSelectedCurrencyTo(_eTo)
92 | }
93 |
94 | const handleSelectFrom = (_eFrom) => {
95 | console.log(" _eFrom ", _eFrom);
96 | setSelectedCurrencySymbol(_eFrom.symbol)
97 | setSelectedCurrencyFrom(_eFrom)
98 | }
99 |
100 | const handleSwap = (_eFrom) => {
101 | setSelectedCurrencyFrom(selectedCurrencyTo);
102 | setSelectedCurrencyTo(selectedCurrencyFrom);
103 | setSelectedCurrencySymbol(selectedCurrencyTo.symbol);
104 | }
105 |
106 | function roundOffToX(x, value) {
107 | return (x) ? value.toFixed(x) : value;
108 | }
109 |
110 | return <>
111 |