diff --git a/client/src/assets/styles/search.scss b/client/src/assets/styles/search.scss
new file mode 100644
index 0000000..a24eee1
--- /dev/null
+++ b/client/src/assets/styles/search.scss
@@ -0,0 +1,75 @@
+.search-sort-container {
+ width: 100%;
+ display: grid;
+ grid-auto-flow: column;
+ justify-content: start;
+}
+
+.search-container {
+
+}
+
+.search-input {
+ display: block;
+ width: 400px;
+ margin-top: 10px;
+ margin-left: 10px;
+ padding: 10px 50px 10px 20px;
+ font-size: 14px;
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
+ Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ color: gray;
+ border-radius: 50px;
+ border: 1px solid gray;
+}
+
+.sort-button {
+ display: grid;
+ padding: 12px 15px;
+ margin: 10px;
+ border-radius: 50px;
+ border: 1px solid gray;
+ color: var(--primary-600);
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
+ Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ font-size: 12px;
+ font-weight: bolder;
+}
+
+.sort-list {
+ padding: 5px;
+ padding-right: 30px;
+ background-color: white;
+ border: 1px solid gray;
+ border-radius: 5px;
+ font-size: 12px;
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
+ Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ :hover {
+ color: #ffa630;
+ cursor: pointer;
+ }
+}
+
+.active {
+ color: #ffa630;
+}
+
+.search {
+ position: relative;
+
+ button {
+ position: absolute;
+ top:0px;
+ right:5px;
+ width: 40px;
+ height: 100%;
+ cursor: pointer;
+ background-color: transparent;
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-position: center;
+ border-radius: 20px;
+ border: 0;
+ }
+}
\ No newline at end of file
diff --git a/client/src/components/Search.jsx b/client/src/components/Search.jsx
new file mode 100644
index 0000000..0e1bedd
--- /dev/null
+++ b/client/src/components/Search.jsx
@@ -0,0 +1,38 @@
+import { useState } from 'react';
+import '../assets/styles/search.scss';
+import { useAppContext } from '../context/appContext';
+
+const Search = (props) => {
+ const [search, setSearch] = useState({
+ value: ''
+ });
+
+ const { getSubscriptions } = useAppContext();
+
+ const handleSubmit = () => {
+ event.preventDefault();
+ getSubscriptions({type: props.type, sort: null, search: search.value})
+ };
+ const handleChange = event => {
+ setSearch({value: event.target.value});
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default Search;
diff --git a/client/src/components/Sort.jsx b/client/src/components/Sort.jsx
new file mode 100644
index 0000000..02b0e08
--- /dev/null
+++ b/client/src/components/Sort.jsx
@@ -0,0 +1,69 @@
+import { useState } from 'react';
+import { useAppContext } from '../context/appContext';
+import '../assets/styles/search.scss';
+
+const Sort = (props) => {
+ //Initialize the sort button's open state to false
+ //Otherwise, the dropdown will be open upon initial render
+ const [sortStatus, setSortStatus] = useState({
+ isOpen: false,
+ activeSortOpt: '',
+ });
+
+ const { activeSortOpt } = sortStatus;
+ const { getSubscriptions } = useAppContext();
+
+ //Sort dropdown options
+ const sortOptions = ['Alphabetical', 'Cost', 'Payment Due'];
+
+ const handleSortOptClick = (e) => {
+ e.preventDefault();
+ getSubscriptions({type: props.type, sort: e.target.innerText.toLowerCase()});
+ setSortStatus({ isOpen: false, activeSortOpt: e.target.innerText });
+ };
+
+ //handler that is invoked upon clicking on sort button, toggling its open status to the opposite boolean
+ const handleSortClick = () => {
+ //invoke funtion in appContext here
+ //dispatch action?
+ setSortStatus((sortStatus) => {
+ return {
+ ...sortStatus,
+ isOpen: !sortStatus.isOpen,
+ };
+ });
+ };
+
+ //Map dropdown options to li component
+ const sortListItems = sortOptions.map(el => {
+ //If the list item was selected, provide dynamic className for dynamic styling
+ //Will let user know which sort option is currently active
+ let activeClass = activeSortOpt === el ? 'active sort-list-item' : 'sort-list-item';
+
+ return (
+
+ {el}
+
+ );
+ });
+
+ return (
+
+
+ {sortStatus.isOpen && (
+
+ )}
+
+ );
+};
+
+export default Sort;
diff --git a/client/src/components/index.js b/client/src/components/index.js
index 0aeeb02..03a60a8 100644
--- a/client/src/components/index.js
+++ b/client/src/components/index.js
@@ -4,5 +4,7 @@ import Alert from './Alert';
import Navbar from './Navbar';
import LargeSidebar from './LargeSidebar';
import SmallSidebar from './SmallSidebar';
+import Search from './Search';
+import Sort from './Sort';
-export { Logo, FormRow, Alert, Navbar, LargeSidebar, SmallSidebar };
+export { Logo, FormRow, Alert, Navbar, LargeSidebar, SmallSidebar, Search, Sort };
diff --git a/client/src/context/actions.js b/client/src/context/actions.js
index aac11a2..cf1bdd2 100644
--- a/client/src/context/actions.js
+++ b/client/src/context/actions.js
@@ -20,6 +20,11 @@ const GET_CURRENT_USER_SUCCESS = 'GET_CURRENT_USER_SUCCESS';
const TOGGLE_SIDEBAR = 'TOGGLE_SIDEBAR';
+//Subscriptions
+const GET_SUBSCRIPTIONS_SUCCESS = 'GET_SUBSCRIPTIONS_SUCCESS';
+const GET_SUBSCRIPTIONS_ERROR = 'GET_SUBSCRIPTIONS_ERROR';
+const GET_SUBSCRIPTIONS_BEGIN = 'GET_SUBSCRIPTIONS_BEGIN';
+
export {
DISPLAY_ALERT,
REMOVE_ALERT,
@@ -36,4 +41,7 @@ export {
GET_CURRENT_USER_BEGIN,
GET_CURRENT_USER_SUCCESS,
TOGGLE_SIDEBAR,
+ GET_SUBSCRIPTIONS_SUCCESS,
+ GET_SUBSCRIPTIONS_ERROR,
+ GET_SUBSCRIPTIONS_BEGIN,
};
diff --git a/client/src/context/appContext.js b/client/src/context/appContext.js
index 7ffea06..d6cd1c6 100644
--- a/client/src/context/appContext.js
+++ b/client/src/context/appContext.js
@@ -17,6 +17,9 @@ import {
GET_CURRENT_USER_BEGIN,
GET_CURRENT_USER_SUCCESS,
TOGGLE_SIDEBAR,
+ GET_SUBSCRIPTIONS_BEGIN,
+ GET_SUBSCRIPTIONS_SUCCESS,
+ GET_SUBSCRIPTIONS_ERROR,
} from './actions';
const initialState = {
@@ -36,7 +39,7 @@ const AppProvider = ({ children }) => {
// Axios config
// TODO move to separate file
const authFetch = axios.create({
- baseURL: '/api/v1/',
+ baseURL: '/api/v1',
});
// alternative way to add token to header
@@ -196,6 +199,39 @@ const AppProvider = ({ children }) => {
getCurrentUser();
}, []);
+ //do we want to consider optional parameters at all?
+ const getSubscriptions = async ({ type, sort, search }) => {
+ const url = `/subscriptions?status=${type}&sort=${sort}&search=${search}`;
+
+ try{
+ dispatch({ type: GET_SUBSCRIPTIONS_BEGIN });
+
+ const { data } = await authFetch.get(url);
+ if (!data) {
+ throw new Error('Subscriptions not found');
+ }
+ const { subscriptions } = data;
+ if (!subscriptions) {
+ throw new Error('Subscriptions not found');
+ }
+
+ dispatch({
+ type: GET_SUBSCRIPTIONS_SUCCESS,
+ payload: { subscriptions }
+ });
+ }
+ catch(error){
+ dispatch( {
+ type: GET_SUBSCRIPTIONS_ERROR,
+ payload: {
+ message:
+ error.response?.data?.message || error.message || 'Getting subscriptions failed'
+ }
+ });
+ }
+ clearAlert();
+ };
+
return (
{
toggleSidebar,
logoutUser,
updateUser,
+ getSubscriptions,
}}
>
{children}
diff --git a/client/src/context/reducer.js b/client/src/context/reducer.js
index 5caa010..937d222 100644
--- a/client/src/context/reducer.js
+++ b/client/src/context/reducer.js
@@ -14,6 +14,9 @@ import {
GET_CURRENT_USER_BEGIN,
GET_CURRENT_USER_SUCCESS,
TOGGLE_SIDEBAR,
+ GET_SUBSCRIPTIONS_BEGIN,
+ GET_SUBSCRIPTIONS_ERROR,
+ GET_SUBSCRIPTIONS_SUCCESS,
} from './actions';
import { initialState } from './appContext';
@@ -151,6 +154,32 @@ const reducer = (state, action) => {
};
}
+ if (action.type === GET_SUBSCRIPTIONS_BEGIN) {
+ return { ...state, isLoading: true };
+ }
+
+ if (action.type === GET_SUBSCRIPTIONS_SUCCESS) {
+ return {
+ ...state,
+ isLoading: false,
+ subscriptions: action.payload.subscriptions,
+ }
+ }
+
+ if (action.type === GET_SUBSCRIPTIONS_ERROR) {
+ return {
+ ...state,
+ isLoading: false,
+ showAlert: true,
+ alert: {
+ type: 'danger',
+ message:
+ action.payload.message ||
+ 'Unexpected Error. Subscriptions could not be retrieved.',
+ }
+ }
+ }
+
throw new Error(`Unhandled action type: ${action.type}`);
};
diff --git a/client/src/pages/dashboard/Active.jsx b/client/src/pages/dashboard/Active.jsx
index 04eebba..d8ac609 100644
--- a/client/src/pages/dashboard/Active.jsx
+++ b/client/src/pages/dashboard/Active.jsx
@@ -1,5 +1,20 @@
-const Active = () => {
- return Active Subscription
;
+import { Search, Sort } from '../../components';
+import { useAppContext } from '../../context/appContext';
+import '../../assets/styles/search.scss';
+
+const Active = () => {
+ return (
+
+
Active Subscriptions
+ {/* add a div container to contain the search filter and sort components w/ className for styling*/}
+
+
+
+
+
+ {/* render all cards that have been mapped to an array and/or retrieved from state/contexAPI */}
+
+ );
};
-export default Active;
+export default Active;
\ No newline at end of file
diff --git a/client/src/pages/dashboard/Past.jsx b/client/src/pages/dashboard/Past.jsx
index 3db9250..0a2ee4b 100644
--- a/client/src/pages/dashboard/Past.jsx
+++ b/client/src/pages/dashboard/Past.jsx
@@ -1,5 +1,17 @@
+import { Search, Sort } from '../../components';
+import { useAppContext } from '../../context/appContext';
+import '../../assets/styles/search.scss';
+
const Past = () => {
- return Past
;
+ return (
+
+
Past Subscriptions
+
+
+
+
+
+ );
};
export default Past;
diff --git a/client/src/pages/dashboard/Trial.jsx b/client/src/pages/dashboard/Trial.jsx
index 916437e..190d0e5 100644
--- a/client/src/pages/dashboard/Trial.jsx
+++ b/client/src/pages/dashboard/Trial.jsx
@@ -1,5 +1,17 @@
+import { Search, Sort } from '../../components';
+import { useAppContext } from '../../context/appContext';
+import '../../assets/styles/search.scss';
+
const Trial = () => {
- return Trial
;
+ return (
+
+
Trial Subscriptions
+
+
+
+
+
+ );
};
export default Trial;
diff --git a/package-lock.json b/package-lock.json
index 18e24df..deffc0e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,9 @@
"name": "subslify",
"version": "0.1.0",
"license": "MIT",
+ "dependencies": {
+ "ts-node": "^10.9.1"
+ },
"devDependencies": {
"@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "^5.48.2",
@@ -2055,6 +2058,26 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
"node_modules/@eslint/eslintrc": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
@@ -2128,7 +2151,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
- "dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -2145,8 +2167,7 @@
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
- "dev": true
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.17",
@@ -2230,6 +2251,26 @@
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==",
"dev": true
},
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
+ "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
+ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
+ },
"node_modules/@types/json-schema": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
@@ -2245,8 +2286,7 @@
"node_modules/@types/node": {
"version": "18.11.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
- "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
- "dev": true
+ "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA=="
},
"node_modules/@types/parse-json": {
"version": "4.0.0",
@@ -2492,7 +2532,6 @@
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
"integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
- "dev": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2509,6 +2548,14 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
+ "node_modules/acorn-walk": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -2549,6 +2596,11 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+ },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -2962,6 +3014,11 @@
"node": ">=10"
}
},
+ "node_modules/create-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -3049,6 +3106,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -4654,6 +4719,11 @@
"node": ">=10"
}
},
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+ },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -5461,6 +5531,48 @@
"node": ">=8.0"
}
},
+ "node_modules/ts-node": {
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
+ "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
+ }
+ },
"node_modules/tsconfig-paths": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
@@ -5548,7 +5660,6 @@
"version": "4.9.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
- "dev": true,
"peer": true,
"bin": {
"tsc": "bin/tsc",
@@ -5648,6 +5759,11 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -5744,6 +5860,14 @@
"node": ">= 6"
}
},
+ "node_modules/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index f65800c..8164040 100644
--- a/package.json
+++ b/package.json
@@ -39,5 +39,8 @@
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-react": "^7.32.1",
"prettier": "^2.8.1"
+ },
+ "dependencies": {
+ "ts-node": "^10.9.1"
}
}
diff --git a/server/src/Config/google.ts b/server/src/Config/google.ts
index b4ea1a8..d87f447 100644
--- a/server/src/Config/google.ts
+++ b/server/src/Config/google.ts
@@ -6,7 +6,7 @@ import {
VerifyCallback,
} from 'passport-google-oauth20';
import generator from 'generate-password';
-import BadRequestError from 'src/errors/bad-request.js';
+import { BadRequestError } from '../errors/index.js';
const randomPw: string = generator.generate({
length: 10,
diff --git a/server/src/controllers/subscriptionsController.js b/server/src/controllers/subscriptionsController.js
index fb790df..252323c 100644
--- a/server/src/controllers/subscriptionsController.js
+++ b/server/src/controllers/subscriptionsController.js
@@ -32,6 +32,7 @@ const deleteSubscription = async (req, res) => {
};
const getSubscriptions = async (req, res) => {
+
const user = req.user.id;
const filter = {
user,
diff --git a/server/src/server.ts b/server/src/server.ts
index c2c192d..c7cccb5 100644
--- a/server/src/server.ts
+++ b/server/src/server.ts
@@ -5,6 +5,7 @@ import session from 'express-session';
import passport from 'passport';
import passportConfig from './Config/google.js';
import morgan from 'morgan';
+import authenticateUser from './middleware/auth.js';
// db and authenticateUser
import connectDB from './db/connect.js';
@@ -55,7 +56,7 @@ app.get('/', (_req: Request, res: Response, _next: NextFunction) => {
// Register the authRouter and subscriptionsRouter to their respective endpoints.
app.use('/api/v1/auth', authRouter);
-app.use('/api/v1/subscriptions', subscriptionsRouter);
+app.use('/api/v1/subscriptions', authenticateUser, subscriptionsRouter);
app.use(notFoundMiddleware);
app.use(errorHandlerMiddleware);