);
};
diff --git a/client/src/pages/Profiles/Profiles.test.tsx b/client/src/pages/Profiles/Profiles.test.tsx
index b2b46d0..2966c7f 100644
--- a/client/src/pages/Profiles/Profiles.test.tsx
+++ b/client/src/pages/Profiles/Profiles.test.tsx
@@ -2,6 +2,7 @@ import React from "react";
import { create } from "react-test-renderer";
import { Provider } from "react-redux";
import configureStore from "redux-mock-store";
+import { BrowserRouter } from "react-router-dom";
import Profiles from "./Profiles";
@@ -27,7 +28,9 @@ describe("MainPage Component", () => {
const store = mockStore(initialState);
const tree = create(
).toJSON();
expect(tree).toMatchSnapshot();
diff --git a/client/src/pages/Profiles/Profiles.tsx b/client/src/pages/Profiles/Profiles.tsx
index 1aed94f..54b363b 100644
--- a/client/src/pages/Profiles/Profiles.tsx
+++ b/client/src/pages/Profiles/Profiles.tsx
@@ -1,4 +1,5 @@
import React, { useEffect } from "react";
+import { Link } from "react-router-dom";
import { useAppDispatch, useAppSelector } from "../../app/hooks";
import { fetchProfiles } from "../../features/profiles/profilesSlice";
import ProfileThumb from "../../components/ProfileThumb/ProfileThumb";
@@ -13,13 +14,20 @@ const Profiles = (): JSX.Element => {
return (
<>
-
- {profiles.map((profile) => (
-
- ))}
+
+
PROFILES
+
+
+ {profiles.map((profile, index) => (
+
+
+
+ ))}
+
>
);
diff --git a/client/src/pages/Profiles/__snapshots__/Profiles.test.tsx.snap b/client/src/pages/Profiles/__snapshots__/Profiles.test.tsx.snap
deleted file mode 100644
index 41700c4..0000000
--- a/client/src/pages/Profiles/__snapshots__/Profiles.test.tsx.snap
+++ /dev/null
@@ -1,37 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`MainPage Component renders correctly 1`] = `
-[
-
-
- PROFILES
-
- ,
-
,
-]
-`;
diff --git a/client/types/profile.ts b/client/types/profile.ts
index 6911e62..f7dd63e 100644
--- a/client/types/profile.ts
+++ b/client/types/profile.ts
@@ -1,23 +1,71 @@
-interface ISocial {
- linkedIn?: string;
- github?: string;
+import { Document, ObjectId } from "mongoose";
+
+interface ISocialLinks {
twitter?: string;
- facebook?: string;
- instagram?: string;
+ blog?: string;
+ other?: string[];
+}
+
+interface IProject {
+ name: string;
+ description?: string;
+ link?: string;
}
-interface IJob {
+interface ICareerPosition {
title?: string;
company?: string;
- description?: string;
- date?: Date;
+ startDate?: Date;
+ endDate?: Date;
+}
+
+interface IEducation {
+ institution: string;
+ degree?: string;
+ fieldOfStudy?: string;
+ startDate?: Date;
+ endDate?: Date;
+}
+
+interface ITestimonial {
+ from: string;
+ relation?: string;
+ text: string;
+}
+
+interface IBlogOrWriting {
+ title: string;
+ link: string;
}
-export interface IProfile {
- user: string;
- firstName: string;
- lastName: string;
- bio?: string;
- job?: IJob;
- socials?: ISocial;
+export interface IProfile extends Document {
+ user: ObjectId;
+ fullName: string;
+ profilePhoto?: string;
+ cohort?: string;
+ graduationYear?: number;
+ email?: string;
+ linkedInProfile?: string;
+ professionalSummary?: string;
+ skills?: string[];
+ specializations?: string[];
+ careerInformation?: {
+ currentPosition?: {
+ title?: string;
+ company?: string;
+ };
+ pastPositions?: ICareerPosition[];
+ };
+ education?: IEducation[];
+ projects?: IProject[];
+ personalBio?: string;
+ testimonials?: ITestimonial[];
+ socialMediaLinks?: ISocialLinks;
+ availabilityForNetworking?: boolean;
+ bootcampExperience?: string;
+ achievementsAndCertifications?: string[];
+ volunteerWork?: string[];
+ eventParticipation?: string[];
+ gallery?: string[];
+ blogOrWriting?: IBlogOrWriting[];
}
diff --git a/package-lock.json b/package-lock.json
index 38eb51a..718bf55 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
+ "aws-sdk": "^2.1589.0",
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6",
"dotenv": "^16.3.1",
@@ -17,6 +18,7 @@
"html-webpack-plugin": "^5.5.3",
"jsonwebtoken": "^9.0.1",
"mongoose": "^7.3.4",
+ "multer": "^1.4.5-lts.1",
"react": "^18.2.0",
"webpack": "^5.88.1"
},
@@ -30,6 +32,7 @@
"@types/jest": "^29.5.3",
"@types/jsonwebtoken": "^9.0.2",
"@types/mongoose": "^5.11.97",
+ "@types/multer": "^1.4.11",
"@types/node": "^20.5.1",
"@types/react": "^18.2.39",
"@types/react-test-renderer": "^18.0.7",
@@ -2896,6 +2899,15 @@
"mongoose": "*"
}
},
+ "node_modules/@types/multer": {
+ "version": "1.4.11",
+ "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz",
+ "integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==",
+ "dev": true,
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
"node_modules/@types/node": {
"version": "20.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz",
@@ -3503,6 +3515,11 @@
"node": ">= 8"
}
},
+ "node_modules/append-field": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
+ },
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
@@ -3561,7 +3578,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -3569,6 +3585,43 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/aws-sdk": {
+ "version": "2.1589.0",
+ "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1589.0.tgz",
+ "integrity": "sha512-Tt3UHH6hoUEAjbCscqvfEAoq9VSTN5iSQO9XSisiiH/QJo8sf+iLCYmfJHM4tVkd92bQH61/xxj9t2Mazwc/WQ==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "buffer": "4.9.2",
+ "events": "1.1.1",
+ "ieee754": "1.1.13",
+ "jmespath": "0.16.0",
+ "querystring": "0.2.0",
+ "sax": "1.2.1",
+ "url": "0.10.3",
+ "util": "^0.12.4",
+ "uuid": "8.0.0",
+ "xml2js": "0.6.2"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/aws-sdk/node_modules/events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/aws-sdk/node_modules/uuid": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
+ "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/axios": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
@@ -3716,6 +3769,25 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -3864,6 +3936,16 @@
"node": ">=14.20.1"
}
},
+ "node_modules/buffer": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+ "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+ "dependencies": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
@@ -3874,6 +3956,17 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -4190,6 +4283,47 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
+ "node_modules/concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "engines": [
+ "node >= 0.8"
+ ],
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/concat-stream/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/concat-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "node_modules/concat-stream/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
"node_modules/concurrently": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.0.tgz",
@@ -4306,8 +4440,7 @@
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
- "dev": true
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/create-require": {
"version": "1.1.1",
@@ -5208,7 +5341,6 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
"dependencies": {
"is-callable": "^1.1.3"
}
@@ -5488,7 +5620,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
"dependencies": {
"has-symbols": "^1.0.2"
},
@@ -5836,6 +5967,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+ },
"node_modules/ignore-by-default": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
@@ -5944,7 +6080,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
- "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -6020,7 +6155,6 @@
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -6097,6 +6231,20 @@
"node": ">=6"
}
},
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -6255,7 +6403,6 @@
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
"integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
- "dev": true,
"dependencies": {
"which-typed-array": "^1.1.11"
},
@@ -6303,8 +6450,7 @@
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/isexe": {
"version": "2.0.0",
@@ -7081,6 +7227,14 @@
"node": ">= 10.13.0"
}
},
+ "node_modules/jmespath": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
+ "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -7507,7 +7661,6 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -7636,6 +7789,34 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
+ "node_modules/multer": {
+ "version": "1.4.5-lts.1",
+ "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
+ "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
+ "dependencies": {
+ "append-field": "^1.0.0",
+ "busboy": "^1.0.0",
+ "concat-stream": "^1.5.2",
+ "mkdirp": "^0.5.4",
+ "object-assign": "^4.1.1",
+ "type-is": "^1.6.4",
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/multer/node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
"node_modules/multicast-dns": {
"version": "7.2.5",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
@@ -7818,7 +7999,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8172,8 +8352,7 @@
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/prompts": {
"version": "2.4.2",
@@ -8256,6 +8435,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
+ "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
"node_modules/querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
@@ -8753,6 +8941,11 @@
"node": ">=6"
}
},
+ "node_modules/sax": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
+ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="
+ },
"node_modules/saxes": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
@@ -9250,6 +9443,14 @@
"node": ">= 0.4"
}
},
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -9805,6 +10006,11 @@
"node": ">= 0.6"
}
},
+ "node_modules/typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+ },
"node_modules/typescript": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
@@ -9918,6 +10124,15 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/url": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
+ "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==",
+ "dependencies": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ }
+ },
"node_modules/url-parse": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
@@ -9928,6 +10143,11 @@
"requires-port": "^1.0.0"
}
},
+ "node_modules/url/node_modules/punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
+ },
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
@@ -9937,11 +10157,22 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
+ "node_modules/util": {
+ "version": "0.12.5",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
+ "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "is-typed-array": "^1.1.3",
+ "which-typed-array": "^1.1.2"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/utila": {
"version": "0.4.0",
@@ -10479,7 +10710,6 @@
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
"integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
- "dev": true,
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.4",
@@ -10566,6 +10796,26 @@
"node": ">=12"
}
},
+ "node_modules/xml2js": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
+ "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
+ "dependencies": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/xmlchars": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
@@ -10576,7 +10826,6 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true,
"engines": {
"node": ">=0.4"
}
@@ -12775,6 +13024,15 @@
"mongoose": "*"
}
},
+ "@types/multer": {
+ "version": "1.4.11",
+ "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz",
+ "integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==",
+ "dev": true,
+ "requires": {
+ "@types/express": "*"
+ }
+ },
"@types/node": {
"version": "20.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz",
@@ -13295,6 +13553,11 @@
"picomatch": "^2.0.4"
}
},
+ "append-field": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
+ },
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
@@ -13349,8 +13612,36 @@
"available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "dev": true
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
+ },
+ "aws-sdk": {
+ "version": "2.1589.0",
+ "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1589.0.tgz",
+ "integrity": "sha512-Tt3UHH6hoUEAjbCscqvfEAoq9VSTN5iSQO9XSisiiH/QJo8sf+iLCYmfJHM4tVkd92bQH61/xxj9t2Mazwc/WQ==",
+ "requires": {
+ "buffer": "4.9.2",
+ "events": "1.1.1",
+ "ieee754": "1.1.13",
+ "jmespath": "0.16.0",
+ "querystring": "0.2.0",
+ "sax": "1.2.1",
+ "url": "0.10.3",
+ "util": "^0.12.4",
+ "uuid": "8.0.0",
+ "xml2js": "0.6.2"
+ },
+ "dependencies": {
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="
+ },
+ "uuid": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
+ "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="
+ }
+ }
},
"axios": {
"version": "1.6.2",
@@ -13469,6 +13760,11 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+ },
"batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -13583,6 +13879,16 @@
"resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz",
"integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA=="
},
+ "buffer": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+ "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
@@ -13593,6 +13899,14 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
+ "busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "requires": {
+ "streamsearch": "^1.1.0"
+ }
+ },
"bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -13821,6 +14135,46 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
"concurrently": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.0.tgz",
@@ -13907,8 +14261,7 @@
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
- "dev": true
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"create-require": {
"version": "1.1.1",
@@ -14596,7 +14949,6 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
"requires": {
"is-callable": "^1.1.3"
}
@@ -14794,7 +15146,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
"requires": {
"has-symbols": "^1.0.2"
}
@@ -15054,6 +15405,11 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+ },
"ignore-by-default": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
@@ -15134,7 +15490,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -15188,8 +15543,7 @@
"is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="
},
"is-core-module": {
"version": "2.12.1",
@@ -15233,6 +15587,14 @@
"integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
"dev": true
},
+ "is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
"is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -15337,7 +15699,6 @@
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
"integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
- "dev": true,
"requires": {
"which-typed-array": "^1.1.11"
}
@@ -15370,8 +15731,7 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"isexe": {
"version": "2.0.0",
@@ -15970,6 +16330,11 @@
"supports-color": "^8.0.0"
}
},
+ "jmespath": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
+ "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -16301,8 +16666,7 @@
"minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
},
"mkdirp": {
"version": "1.0.4",
@@ -16384,6 +16748,30 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
+ "multer": {
+ "version": "1.4.5-lts.1",
+ "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
+ "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
+ "requires": {
+ "append-field": "^1.0.0",
+ "busboy": "^1.0.0",
+ "concat-stream": "^1.5.2",
+ "mkdirp": "^0.5.4",
+ "object-assign": "^4.1.1",
+ "type-is": "^1.6.4",
+ "xtend": "^4.0.0"
+ },
+ "dependencies": {
+ "mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "requires": {
+ "minimist": "^1.2.6"
+ }
+ }
+ }
+ },
"multicast-dns": {
"version": "7.2.5",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
@@ -16527,8 +16915,7 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
"object-inspect": {
"version": "1.12.3",
@@ -16784,8 +17171,7 @@
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"prompts": {
"version": "2.4.2",
@@ -16843,6 +17229,11 @@
"side-channel": "^1.0.4"
}
},
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="
+ },
"querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
@@ -17204,6 +17595,11 @@
"sparse-bitfield": "^3.0.3"
}
},
+ "sax": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
+ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="
+ },
"saxes": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
@@ -17605,6 +18001,11 @@
"internal-slot": "^1.0.4"
}
},
+ "streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="
+ },
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -17972,6 +18373,11 @@
"mime-types": "~2.1.24"
}
},
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+ },
"typescript": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
@@ -18040,6 +18446,22 @@
"punycode": "^2.1.0"
}
},
+ "url": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
+ "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
+ }
+ }
+ },
"url-parse": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
@@ -18057,11 +18479,22 @@
"dev": true,
"requires": {}
},
+ "util": {
+ "version": "0.12.5",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
+ "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "is-typed-array": "^1.1.3",
+ "which-typed-array": "^1.1.2"
+ }
+ },
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"utila": {
"version": "0.4.0",
@@ -18446,7 +18879,6 @@
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
"integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
- "dev": true,
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.4",
@@ -18501,6 +18933,20 @@
"integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
"dev": true
},
+ "xml2js": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
+ "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
+ "requires": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ }
+ },
+ "xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
+ },
"xmlchars": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
@@ -18510,8 +18956,7 @@
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"y18n": {
"version": "5.0.8",
diff --git a/package.json b/package.json
index bf9c22d..9ff156c 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
},
"homepage": "https://github.com/Code-Hammers/code-hammers#readme",
"dependencies": {
+ "aws-sdk": "^2.1589.0",
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6",
"dotenv": "^16.3.1",
@@ -35,6 +36,7 @@
"html-webpack-plugin": "^5.5.3",
"jsonwebtoken": "^9.0.1",
"mongoose": "^7.3.4",
+ "multer": "^1.4.5-lts.1",
"react": "^18.2.0",
"webpack": "^5.88.1"
},
@@ -48,6 +50,7 @@
"@types/jest": "^29.5.3",
"@types/jsonwebtoken": "^9.0.2",
"@types/mongoose": "^5.11.97",
+ "@types/multer": "^1.4.11",
"@types/node": "^20.5.1",
"@types/react": "^18.2.39",
"@types/react-test-renderer": "^18.0.7",
diff --git a/server/controllers/imageController.ts b/server/controllers/imageController.ts
new file mode 100644
index 0000000..8acbbb0
--- /dev/null
+++ b/server/controllers/imageController.ts
@@ -0,0 +1,76 @@
+import { Request, Response, NextFunction } from "express";
+import Profile from "../models/profileModel";
+import AWS from "aws-sdk";
+
+AWS.config.update({
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
+ region: process.env.AWS_REGION,
+});
+
+const s3 = new AWS.S3();
+
+export const uploadProfilePicture = async (
+ req: Request,
+ res: Response,
+ next: NextFunction
+) => {
+ if (!req.file) {
+ return res.status(400).send("No file uploaded.");
+ }
+
+ const { userID } = req.params;
+
+ const file = req.file as Express.Multer.File;
+ const s3Key = `profile-pictures/${Date.now()}_${file.originalname}`;
+
+ let params = {
+ Bucket: process.env.BUCKET_NAME as string,
+ Key: s3Key,
+ Body: file.buffer,
+ ContentType: file.mimetype,
+ ACL: "private",
+ };
+
+ console.log("params.Body", params.Body);
+ console.log(req.file);
+
+ try {
+ const uploadResult = await s3.upload(params).promise();
+ const updatedProfile = await Profile.findOneAndUpdate(
+ { user: userID },
+ { profilePhoto: s3Key },
+ { new: true }
+ );
+
+ const presignedUrl = s3.getSignedUrl("getObject", {
+ Bucket: process.env.BUCKET_NAME,
+ Key: s3Key,
+ Expires: 60 * 5,
+ });
+ if (updatedProfile) {
+ updatedProfile.profilePhoto = presignedUrl;
+ }
+ res.status(201).send(updatedProfile);
+ } catch (err) {
+ console.error("Error uploading to S3:", err);
+ }
+};
+
+//TODO Currently not being used. Built into getProfileByID controller.
+export const generatePresignedUrl = (req: Request, res: Response) => {
+ const key = req.query.key;
+ const params = {
+ Bucket: process.env.BUCKET_NAME,
+ Key: key as string,
+ Expires: 60,
+ };
+
+ s3.getSignedUrl("putObject", params, (err, url) => {
+ if (err) {
+ console.error("Error generating URL:", err);
+ return res.status(500).send("Error generating URL");
+ }
+ res.status(200).send({ message: "URL generated successfully", url });
+ });
+};
diff --git a/server/controllers/profileController.ts b/server/controllers/profileController.ts
index 70e8928..1d284d0 100644
--- a/server/controllers/profileController.ts
+++ b/server/controllers/profileController.ts
@@ -1,6 +1,15 @@
import Profile from "../models/profileModel";
import { Request, Response, NextFunction } from "express";
import { IProfile } from "../types/profile";
+import AWS from "aws-sdk";
+
+AWS.config.update({
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
+ region: process.env.AWS_REGION,
+});
+
+const s3 = new AWS.S3();
// ENDPOINT POST api/profiles/create
// PURPOSE Create a new profile
@@ -10,31 +19,75 @@ const createProfile = async (
res: Response,
next: NextFunction
) => {
- const { user, firstName, lastName, bio, job, socials } = req.body;
+ const {
+ user,
+ fullName,
+ profilePhoto,
+ cohort,
+ graduationYear,
+ email,
+ linkedInProfile,
+ professionalSummary,
+ skills,
+ specializations,
+ careerInformation,
+ education,
+ projects,
+ personalBio,
+ testimonials,
+ socialMediaLinks,
+ availabilityForNetworking,
+ bootcampExperience,
+ achievementsAndCertifications,
+ volunteerWork,
+ eventParticipation,
+ gallery,
+ blogOrWriting,
+ } = req.body;
try {
- const profile: IProfile = await Profile.create({
+ const profile = await Profile.create({
user,
- firstName,
- lastName,
- bio,
- job,
- socials,
+ fullName,
+ profilePhoto,
+ cohort,
+ graduationYear,
+ email,
+ linkedInProfile,
+ professionalSummary,
+ skills,
+ specializations,
+ careerInformation,
+ education,
+ projects,
+ personalBio,
+ testimonials,
+ socialMediaLinks,
+ availabilityForNetworking,
+ bootcampExperience,
+ achievementsAndCertifications,
+ volunteerWork,
+ eventParticipation,
+ gallery,
+ blogOrWriting,
});
if (profile) {
return res.status(201).json(profile);
}
} catch (error) {
+ console.error(error);
return next({
log: "Express error in createProfile Middleware",
status: 500,
- message: { err: "An error occurred during profile creation" },
+ message: {
+ err: "An error occurred during profile creation. Please try again.",
+ },
});
}
};
-// ENDPOINT PATCH api/profiles/:UserID
+// ENDPOINT PUT api/profiles/:UserID
// PURPOSE Update an existing profile
// ACCESS Private
const updateProfile = async (
@@ -43,13 +96,12 @@ const updateProfile = async (
next: NextFunction
) => {
const { userID } = req.params;
- const { firstName, lastName, bio, job, socials } = req.body;
+ const { fullName, email, personalBio } = req.body;
+
const newProfile = {
- firstName,
- lastName,
- bio,
- job,
- socials,
+ fullName,
+ email,
+ personalBio,
};
try {
@@ -95,7 +147,21 @@ const getAllProfiles = async (
message: { err: "There were no profiles to retrieve" },
});
} else {
- return res.status(201).json(profiles);
+ const processedProfiles = await Promise.all(
+ profiles.map(async (profile) => {
+ if (profile.profilePhoto) {
+ const presignedUrl = s3.getSignedUrl("getObject", {
+ Bucket: process.env.BUCKET_NAME,
+ Key: profile.profilePhoto,
+ Expires: 60 * 5,
+ });
+ profile.profilePhoto = presignedUrl;
+ }
+ return profile.toObject();
+ })
+ );
+
+ return res.status(201).json(processedProfiles);
}
} catch (error) {
return next({
@@ -124,9 +190,17 @@ const getProfileById = async (
status: 404,
message: { err: "An error occurred during profile retrieval" },
});
- } else {
- return res.status(200).json(profile);
}
+ if (profile.profilePhoto) {
+ const presignedUrl = s3.getSignedUrl("getObject", {
+ Bucket: process.env.BUCKET_NAME,
+ Key: profile.profilePhoto,
+ Expires: 60 * 5,
+ });
+ profile.profilePhoto = presignedUrl;
+ }
+
+ return res.status(200).json(profile);
} catch (error) {
return next({
log: "Express error in getProfileById Middleware",
diff --git a/server/index.ts b/server/index.ts
index a189f85..0250901 100644
--- a/server/index.ts
+++ b/server/index.ts
@@ -3,6 +3,7 @@ import express, { Request, Response, Application, NextFunction } from "express";
import userRoutes from "./routes/userRoutes";
import profileRoutes from "./routes/profileRoutes";
import authRoutes from "./routes/authRoutes";
+import imageRoutes from "./routes/imageRoutes";
import connectDB from "./config/db";
import dotenv from "dotenv";
import cookieParser from "cookie-parser";
@@ -20,6 +21,7 @@ connectDB();
app.use("/api/users", userRoutes);
app.use("/api/profiles", profileRoutes);
app.use("/api/auth", authRoutes);
+app.use("/api/images", imageRoutes);
console.log(`ENV BEFORE CHECK: ${process.env.NODE_ENV}`);
diff --git a/server/models/profileModel.ts b/server/models/profileModel.ts
index 308c38c..bfdd800 100644
--- a/server/models/profileModel.ts
+++ b/server/models/profileModel.ts
@@ -1,46 +1,74 @@
-import mongoose from "mongoose";
+import mongoose, { Schema } from "mongoose";
import { IProfile } from "../types/profile";
-const profileSchema = new mongoose.Schema
({
- user: {
- type: mongoose.Schema.Types.ObjectId,
- ref: "User",
- required: true,
- },
- bio: {
- type: String,
- },
- firstName: {
- type: String,
- },
- lastName: {
- type: String,
- },
- job: {
- title: String,
- company: String,
- description: String,
- date: Date,
- },
- socials: {
- linkedIn: {
- type: String,
- },
- github: {
- type: String,
+const profileSchema = new Schema({
+ user: { type: Schema.Types.ObjectId, ref: "User", required: true },
+ fullName: { type: String, required: true },
+ profilePhoto: String,
+ cohort: String,
+ graduationYear: Number,
+ email: String,
+ linkedInProfile: String,
+ professionalSummary: String,
+ skills: [String],
+ specializations: [String],
+ careerInformation: {
+ currentPosition: {
+ title: String,
+ company: String,
},
- twitter: {
- type: String,
+ pastPositions: [
+ {
+ title: String,
+ company: String,
+ startDate: Date,
+ endDate: Date,
+ },
+ ],
+ },
+ education: [
+ {
+ institution: String,
+ degree: String,
+ fieldOfStudy: String,
+ startDate: Date,
+ endDate: Date,
},
- facebook: {
- type: String,
+ ],
+ projects: [
+ {
+ name: String,
+ description: String,
+ link: String,
},
- instagram: {
- type: String,
+ ],
+ personalBio: String,
+ testimonials: [
+ {
+ from: String,
+ relation: String,
+ text: String,
},
+ ],
+ socialMediaLinks: {
+ twitter: String,
+ blog: String,
+ other: [String],
},
+ availabilityForNetworking: Boolean,
+ bootcampExperience: String,
+ achievementsAndCertifications: [String],
+ volunteerWork: [String],
+ eventParticipation: [String],
+ gallery: [String],
+ blogOrWriting: [
+ {
+ title: String,
+ link: String,
+ },
+ ],
});
-const Profile = mongoose.model("Profile", profileSchema);
+const Profile = mongoose.model("profiles", profileSchema);
export default Profile;
diff --git a/server/models/userModel.ts b/server/models/userModel.ts
index ffcfcf4..f5aaadd 100644
--- a/server/models/userModel.ts
+++ b/server/models/userModel.ts
@@ -1,8 +1,8 @@
-import mongoose, { Document } from "mongoose";
+import mongoose, { Schema } from "mongoose";
import bcrypt from "bcryptjs";
import { IUser } from "../types/user";
-const userSchema = new mongoose.Schema({
+const userSchema = new Schema({
firstName: {
type: String,
required: true,
diff --git a/server/routes/imageRoutes.ts b/server/routes/imageRoutes.ts
new file mode 100644
index 0000000..1eb11a0
--- /dev/null
+++ b/server/routes/imageRoutes.ts
@@ -0,0 +1,23 @@
+import express from "express";
+import {
+ uploadProfilePicture,
+ generatePresignedUrl,
+} from "../controllers/imageController";
+import { protect } from "../middleware/authMiddleware";
+
+const router = express.Router();
+
+import multer from "multer";
+const storage = multer.memoryStorage();
+const upload = multer({ storage: storage });
+
+router.post(
+ "/profile-picture/:userID",
+ upload.single("profilePicture"),
+ uploadProfilePicture
+);
+
+//TODO Not currently being used
+router.get("/generate-url", generatePresignedUrl);
+
+export default router;
diff --git a/server/routes/profileRoutes.ts b/server/routes/profileRoutes.ts
index 5b843d2..802c050 100644
--- a/server/routes/profileRoutes.ts
+++ b/server/routes/profileRoutes.ts
@@ -10,7 +10,7 @@ import {
const router = express.Router();
router.post("/", createProfile);
-router.patch("/:userID", updateProfile);
+router.put("/:userID", updateProfile);
router.get("/:userID", getProfileById);
router.get("/", getAllProfiles);
diff --git a/server/types/profile.ts b/server/types/profile.ts
index b0e2056..f7dd63e 100644
--- a/server/types/profile.ts
+++ b/server/types/profile.ts
@@ -1,25 +1,71 @@
import { Document, ObjectId } from "mongoose";
-interface ISocial {
- linkedIn?: string;
- github?: string;
+interface ISocialLinks {
twitter?: string;
- facebook?: string;
- instagram?: string;
+ blog?: string;
+ other?: string[];
}
-interface IJob {
+interface IProject {
+ name: string;
+ description?: string;
+ link?: string;
+}
+
+interface ICareerPosition {
title?: string;
company?: string;
- description?: string;
- date?: Date;
+ startDate?: Date;
+ endDate?: Date;
+}
+
+interface IEducation {
+ institution: string;
+ degree?: string;
+ fieldOfStudy?: string;
+ startDate?: Date;
+ endDate?: Date;
+}
+
+interface ITestimonial {
+ from: string;
+ relation?: string;
+ text: string;
+}
+
+interface IBlogOrWriting {
+ title: string;
+ link: string;
}
export interface IProfile extends Document {
user: ObjectId;
- firstName: String;
- lastName: String;
- bio?: string;
- job?: IJob;
- socials?: ISocial;
+ fullName: string;
+ profilePhoto?: string;
+ cohort?: string;
+ graduationYear?: number;
+ email?: string;
+ linkedInProfile?: string;
+ professionalSummary?: string;
+ skills?: string[];
+ specializations?: string[];
+ careerInformation?: {
+ currentPosition?: {
+ title?: string;
+ company?: string;
+ };
+ pastPositions?: ICareerPosition[];
+ };
+ education?: IEducation[];
+ projects?: IProject[];
+ personalBio?: string;
+ testimonials?: ITestimonial[];
+ socialMediaLinks?: ISocialLinks;
+ availabilityForNetworking?: boolean;
+ bootcampExperience?: string;
+ achievementsAndCertifications?: string[];
+ volunteerWork?: string[];
+ eventParticipation?: string[];
+ gallery?: string[];
+ blogOrWriting?: IBlogOrWriting[];
}