diff --git a/package-lock.json b/package-lock.json index 3618706..ae7c776 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@emotion/react": "^11.9.3", "@emotion/styled": "^11.9.3", + "@faker-js/faker": "^7.6.0", "@mui/icons-material": "^5.10.3", "@mui/material": "^5.8.5", "aws-amplify": "^4.3.24", @@ -7748,6 +7749,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@faker-js/faker": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", + "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==", + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -38059,6 +38069,11 @@ } } }, + "@faker-js/faker": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", + "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==" + }, "@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", diff --git a/package.json b/package.json index feae1ef..99803ef 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "dependencies": { "@emotion/react": "^11.9.3", "@emotion/styled": "^11.9.3", + "@faker-js/faker": "^7.6.0", "@mui/icons-material": "^5.10.3", "@mui/material": "^5.8.5", "aws-amplify": "^4.3.24", diff --git a/src/api/data.js b/src/api/data.js index fcb6f50..52285bc 100644 --- a/src/api/data.js +++ b/src/api/data.js @@ -1,3 +1,5 @@ +import { faker } from "@faker-js/faker"; + export const CATEGORIES = [ "FOOD", "FASHION", @@ -101,7 +103,9 @@ export const collaborations = [ proposal: 1, state: "APPLIED", application: { - details: "Influencer 1 application details ", + details: faker.random.words(faker.random.numeric(2)), + posts: 2, + reels: 0, }, influencer: 1, }, @@ -110,7 +114,9 @@ export const collaborations = [ proposal: 1, state: "APPLIED", application: { - details: "Influencer 4 application details ", + details: faker.random.words(faker.random.numeric(2)), + posts: 0, + reels: 1, }, influencer: 4, }, @@ -119,7 +125,9 @@ export const collaborations = [ proposal: 1, state: "APPLIED", application: { - details: "Influencer 5 application details ", + details: faker.random.words(faker.random.numeric(2)), + posts: 1, + reels: 1, }, influencer: 5, }, @@ -128,7 +136,9 @@ export const collaborations = [ proposal: 1, state: "APPROVED", application: { - details: "Influencer 2 application details", + details: faker.random.words(faker.random.numeric(2)), + posts: 3, + reels: 0, }, influencer: 2, }, @@ -137,7 +147,9 @@ export const collaborations = [ proposal: 1, state: "REJECTED", application: { - details: "Influencer 3 application details", + details: faker.random.words(faker.random.numeric(2)), + posts: 0, + reels: 1, }, influencer: 3, }, @@ -146,14 +158,13 @@ export const collaborations = [ export const proposals = [ { id: 1, - title: - "Ipsum ipsum do qui Lorem ex proident consectetur do deserunt adipisicing ipsum. Reprehenderit duis magna do culpa non adipisicing dolore labore enim qui incididunt nisi anim. Occaecat anim enim velit occaecat aliqua pariatur id nisi. Esse esse ex laborum voluptate sit. Pariatur dolore occaecat et dolor ex.", + title: "Organic Cocktails", creativeGuidance: - "Exercitation elit quis duis excepteur velit labore in sit Lorem in Lorem.", - name: "name", - image: "https://dummyimage.com/300", - values: ["ORGANIC"], - categories: ["FOOD"], + "advice or information aimed at resolving a problem or difficulty, especially as given by someone in authority. eg He looked to his father for inspiration and guidance", + name: "OrganiGin Cafe", + image: faker.image.abstract(300, 300, true), + values: ["SUSTAINABLE", "ORGANIC", "RECYCLED", "VEGAN"], + categories: ["FOOD", "FASHION", "FITNESS", "PET", "CATEGORY5"], created: "2022-10-24T01:02:02.012Z", proposalMonth: "December", proposalYear: "2022", @@ -167,7 +178,7 @@ export const proposals = [ image: "https://dummyimage.com/300", values: ["ORGANIC"], categories: ["FOOD"], - created: "2022-10-29T11:22:32.012Z", + created: "2022-10-21T11:22:32.012Z", proposalMonth: "November", proposalYear: "2022", }, @@ -184,3 +195,116 @@ export const proposals = [ proposalYear: "2023", }, ]; + +export const influencers = [ + { + id: 1, + givenName: "Harry", + familyName: "Potter", + email: "hp@hogwarts.wiz", + instaHandle: "harry_scar", + website: "https://hp.hogwarts.wiz", + address: "4 Privit Drive, Surrey WD25 7LR", + bio: "Harry James[58] Potter (b. 31 July 1980)[1] was an English half-blood[2] wizard, and one of the most famous wizards of modern times. The only child and son of James and Lily Potter (née Evans), Harry's birth was overshadowed by a prophecy, naming either himself or Neville Longbottom as the one with the power to vanquish Lord Voldemort, the most powerful and feared Dark Wizard in the world. After half of the prophecy was reported to Voldemort, courtesy of Severus Snape, Harry was chosen as the target due to his many similarities with the Dark Lord. In turn, this caused the Potter family to go into hiding.", + image: faker.image.abstract(300, 300, true), + audienceAge13To17Split: 10, + audienceAge18To24Split: 10, + audienceAge25To34Split: 10, + audienceAge35To44Split: 20, + audienceAge45To54Split: 20, + audienceAge55To64Split: 20, + audienceAge65PlusSplit: 10, + audienceFemaleSplit: 50, + audienceMaleSplit: 50, + CATEGORIES: ["FOOD", "FASHION", "FITNESS"], + VALUES: ["SUSTAINABLE", "ORGANIC", "RECYCLED", "VEGAN"], + }, + { + id: 2, + givenName: faker.name.firstName(), + familyName: faker.name.lastName(), + email: faker.internet.email(), + instaHandle: faker.name.middleName(), + website: faker.internet.url(), + address: faker.address.streetAddress(), + bio: faker.random.words(45), + image: faker.image.abstract(300, 300, true), + audienceAge13To17Split: 10, + audienceAge18To24Split: 10, + audienceAge25To34Split: 10, + audienceAge35To44Split: 20, + audienceAge45To54Split: 20, + audienceAge55To64Split: 20, + audienceAge65PlusSplit: 10, + audienceFemaleSplit: 50, + audienceMaleSplit: 50, + CATEGORIES: ["FOOD", "FASHION", "FITNESS"], + VALUES: ["SUSTAINABLE", "ORGANIC", "RECYCLED", "VEGAN"], + }, + { + id: 3, + givenName: faker.name.firstName(), + familyName: faker.name.lastName(), + email: faker.internet.email(), + instaHandle: faker.name.middleName(), + website: faker.internet.url(), + address: faker.address.streetAddress(), + bio: faker.random.words(45), + image: faker.image.abstract(300, 300, true), + audienceAge13To17Split: 10, + audienceAge18To24Split: 10, + audienceAge25To34Split: 10, + audienceAge35To44Split: 20, + audienceAge45To54Split: 20, + audienceAge55To64Split: 20, + audienceAge65PlusSplit: 10, + audienceFemaleSplit: 50, + audienceMaleSplit: 50, + CATEGORIES: ["FOOD", "FASHION", "FITNESS"], + VALUES: ["SUSTAINABLE", "ORGANIC", "RECYCLED", "VEGAN"], + }, + { + id: 4, + givenName: faker.name.firstName(), + familyName: faker.name.lastName(), + email: faker.internet.email(), + instaHandle: faker.name.middleName(), + website: faker.internet.url(), + address: faker.address.streetAddress(), + bio: faker.random.words(45), + image: faker.image.abstract(300, 300, true), + audienceAge13To17Split: 10, + audienceAge18To24Split: 10, + audienceAge25To34Split: 10, + audienceAge35To44Split: 20, + audienceAge45To54Split: 20, + audienceAge55To64Split: 20, + audienceAge65PlusSplit: 10, + audienceFemaleSplit: 50, + audienceMaleSplit: 50, + CATEGORIES: ["FOOD", "FASHION", "FITNESS"], + VALUES: ["SUSTAINABLE", "ORGANIC", "RECYCLED", "VEGAN"], + }, + { + id: 5, + givenName: faker.name.firstName(), + familyName: faker.name.lastName(), + email: faker.internet.email(), + instaHandle: faker.name.middleName(), + website: faker.internet.url(), + address: faker.address.streetAddress(), + bio: faker.random.words(45), + image: faker.image.abstract(300, 300, true), + audienceAge13To17Split: 10, + audienceAge18To24Split: 10, + audienceAge25To34Split: 10, + audienceAge35To44Split: 20, + audienceAge45To54Split: 20, + audienceAge55To64Split: 20, + audienceAge65PlusSplit: 10, + audienceFemaleSplit: 50, + audienceMaleSplit: 50, + CATEGORIES: ["FOOD", "FASHION", "FITNESS"], + VALUES: ["SUSTAINABLE", "ORGANIC", "RECYCLED", "VEGAN"], + }, +]; diff --git a/src/containers/App.js b/src/containers/App.js index 6733f4a..b61bc9b 100644 --- a/src/containers/App.js +++ b/src/containers/App.js @@ -23,6 +23,7 @@ import { ProposalStep4 } from "../presentation/proposal/ProposalStep4"; import { Values } from "../presentation/values/Values"; import { YourDetails } from "../presentation/YourDetails"; import { Dev } from "../test/Dev"; +import { CollaborationList } from "./collaborations/CollaborationList"; import { Dashboard } from "./Dashboard"; import HomePage from "./HomePage"; import { OnboardingSteps } from "./onboading/OnboardingSteps"; @@ -97,6 +98,18 @@ function App() { /> } /> } /> + } + /> + } + /> + } + /> { + const params = useParams(); + const [openListing, setOpenListing] = React.useState(true); + const [collaborations, setCollaborations] = React.useState([]); + const [proposal, setProposal] = React.useState(undefined); + useEffect(() => { + const filtered = data.filter((c) => { + return parseInt(params.id) === c.proposal && c.state === state; + }); + setCollaborations(filtered); + const prop = proposals.find((p) => { + return p.id === parseInt(params.id); + }); + setProposal(prop); + }, [state, params]); + + if (collaborations.length === 0) + return `No ${state} collaborations available`; + if (!proposal) return "Loading..."; + const influencer = (id) => { + return influencers.find((f) => f.id === id); + }; + const formatState = (str) => { + return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); + }; + + const toggleOpenListing = () => { + setOpenListing(!openListing); + }; + return ( + <> + + + + + Listing Details + + + {openListing ? : } + + + + + + + + + + + {proposal.title} + {proposal.name} + + + + + + + + + Categories + + + + + + Values + + + + + + + + + + Influencers that have {formatState(state)} + + + + {collaborations.map((c) => { + const creator = influencer(c.influencer); + return ( + + + + {`${creator.givenName} ${creator.familyName}`} + + + + {c.application.posts} + + + {c.application.reels} + + + + + + ); + })} + + + ); +}; diff --git a/src/containers/proposals/NewCollaborationProposal.js b/src/containers/proposals/NewCollaborationProposal.js index db4363c..c4d12cb 100644 --- a/src/containers/proposals/NewCollaborationProposal.js +++ b/src/containers/proposals/NewCollaborationProposal.js @@ -1,3 +1,4 @@ +import { Box, Typography } from "@mui/material"; import React from "react"; import { useNavigate } from "react-router"; import { v4 as uuid } from "uuid"; @@ -79,6 +80,9 @@ export const NewCollaborationProposal = () => { return ( <> + + New Listing + { - const theme = useTheme(); const nav = useNavigate(); const [proposals, setProposals] = React.useState([]); @@ -31,16 +31,11 @@ export const ProposalList = () => { }, []); return ( - - Create a{" "} - - New Collaboration Proposal - - + + + My Listings ({proposals.length}) @@ -56,9 +51,11 @@ export const ProposalList = () => { justifyContent: "space-between", cursor: "pointer", }} - onClick={() => handleClick(p)} > - + handleClick(p)} + style={{ whiteSpace: "nowrap", marginRight: "10px" }} + > { marginRight: "10px", }} > - {p.title} - {p.name} + handleClick(p)} style={text}> + {p.title} + + handleClick(p)} style={text}> + {p.name} + + - {/* - - */} + handleClick(p)}> diff --git a/src/containers/proposals/ProposalView.js b/src/containers/proposals/ProposalView.js index a097aa9..0f456bb 100644 --- a/src/containers/proposals/ProposalView.js +++ b/src/containers/proposals/ProposalView.js @@ -1,10 +1,9 @@ -import { useTheme } from "@emotion/react"; -import { Stack, Typography } from "@mui/material"; +import { Stack } from "@mui/material"; import React, { useEffect } from "react"; import { useParams } from "react-router"; -import { Link } from "react-router-dom"; import { collaborations, proposals } from "../../api/data"; import { BackLink } from "../../presentation/BackLink"; +import { CollaborationsStateCounts } from "../../presentation/CollaborationsStateCounts"; import { ProposalStep1 } from "../../presentation/proposal/ProposalStep1"; import { ProposalStep2 } from "../../presentation/proposal/ProposalStep2"; import { ProposalStep3 } from "../../presentation/proposal/ProposalStep3"; @@ -12,32 +11,15 @@ import { ProposalStep4 } from "../../presentation/proposal/ProposalStep4"; import { ProfileCard } from "../profile/ProfileCard"; export const ProposalView = () => { - const theme = useTheme(); // 👇️ get ID from url const params = useParams(); const [proposal, setProposal] = React.useState(undefined); - const [applied, setApplied] = React.useState(0); - const [approved, setApproved] = React.useState(0); - const [rejected, setRejected] = React.useState(0); - const collaborationActionStyle = { - cursor: "pointer", - color: theme.palette.primary.main, - }; useEffect(() => { const proposal = proposals.filter((p) => { return p.id === params.id || p.id === parseInt(params.id); })[0]; setProposal(proposal); - - const collabs = collaborations.filter( - (c) => c.proposal === parseInt(params.id) - ); - const counts = groupBy(collabs, "state"); - - setApplied(counts.APPLIED.length); - setApproved(counts.APPROVED.length); - setRejected(counts.REJECTED.length); }, [params]); if (!proposal) return "Loading..."; @@ -46,50 +28,11 @@ export const ProposalView = () => { - - Collaborations - - - - Applied ({applied}) - - - - - Approved ({approved}) - - - - - Rejected ({rejected}) - - - - + @@ -109,17 +52,3 @@ export const ProposalView = () => { ); }; - -function groupBy(objectArray, property) { - return objectArray.reduce( - function (acc, obj) { - var key = obj[property]; - if (!acc[key]) { - acc[key] = []; - } - acc[key].push(obj); - return acc; - }, - { APPLIED: [], APPROVED: [], REJECTED: [] } - ); -} diff --git a/src/presentation/CollaborationsStateCounts.js b/src/presentation/CollaborationsStateCounts.js new file mode 100644 index 0000000..6d55a51 --- /dev/null +++ b/src/presentation/CollaborationsStateCounts.js @@ -0,0 +1,82 @@ +import { Stack, Typography, useTheme } from "@mui/material"; +import React from "react"; +import { Link } from "react-router-dom"; + +export const CollaborationsStateCounts = (props) => { + const { hideTitle, collaborations, proposalId } = props; + const theme = useTheme(); + const collaborationActionStyle = { + color: theme.palette.primary.main, + }; + const labelStyle = { + fontSize: "0.6rem", + }; + const baseUrl = `/proposal/view/${proposalId}/collaborations`; + + const [applied, setApplied] = React.useState(0); + const [approved, setApproved] = React.useState(0); + const [rejected, setRejected] = React.useState(0); + + React.useEffect(() => { + const collabs = collaborations.filter( + (c) => c.proposal === parseInt(proposalId) + ); + const counts = groupBy(collabs, "state"); + + setApplied(counts.APPLIED.length); + setApproved(counts.APPROVED.length); + setRejected(counts.REJECTED.length); + }, [collaborations, proposalId]); + + return ( + + {!hideTitle && Collaborations} + + + + Applied ({applied}) + + + + + Approved ({approved}) + + + + + Rejected ({rejected}) + + + + + ); +}; + +function groupBy(objectArray, property) { + return objectArray.reduce( + function (acc, obj) { + var key = obj[property]; + if (!acc[key]) { + acc[key] = []; + } + acc[key].push(obj); + return acc; + }, + { APPLIED: [], APPROVED: [], REJECTED: [] } + ); +} diff --git a/src/presentation/categories/Categories.js b/src/presentation/categories/Categories.js index 0ad735a..1821512 100644 --- a/src/presentation/categories/Categories.js +++ b/src/presentation/categories/Categories.js @@ -2,11 +2,12 @@ import { Chip, Grid } from "@mui/material"; import React from "react"; import { CATEGORIES } from "../../api/data"; -export const Categories = ({ data, handleChange, view }) => { +export const Categories = ({ data, handleChange, view, size }) => { const renderChip = (c) => { return ( handleChange(c, "categories")} @@ -15,7 +16,7 @@ export const Categories = ({ data, handleChange, view }) => { ); }; return ( - + {view ? data.categories.map((c) => { return renderChip(c); diff --git a/src/presentation/values/Values.js b/src/presentation/values/Values.js index 26a81ca..a75d52b 100644 --- a/src/presentation/values/Values.js +++ b/src/presentation/values/Values.js @@ -2,11 +2,12 @@ import { Chip, Grid } from "@mui/material"; import React from "react"; import { VALUES } from "../../api/data"; -export const Values = ({ data, handleChange, view }) => { +export const Values = ({ data, handleChange, view, size }) => { const renderChip = (v) => { return ( handleChange(v, "values")} @@ -15,7 +16,7 @@ export const Values = ({ data, handleChange, view }) => { ); }; return ( - + {view ? data.values.map((v) => { return renderChip(v);