diff --git a/src/api/data.js b/src/api/data.js index c8edd3a..17aab2e 100644 --- a/src/api/data.js +++ b/src/api/data.js @@ -161,12 +161,25 @@ const collaboration = (listing, influencer) => { }; }; +const maxTwoDigits = (n) => { + let result = faker.random.numeric(2); + while (result > n) { + result = faker.random.numeric(2); + } + + return result; +}; + +const capitalise = (s) => { + return s.charAt(0).toUpperCase() + s.toLowerCase().slice(1); +}; + const listing = () => { return { id: uuid(), - title: faker.random.words(), - creativeGuidance: faker.random.words(10), - name: `${faker.word.noun()} ${faker.word.noun()}`, + title: capitalise(faker.random.words(maxTwoDigits(18))), + creativeGuidance: capitalise(faker.random.words(10)), + name: capitalise(faker.random.words(maxTwoDigits(18))), image: faker.image.food(300, 300, true), values: randomSelection( VALUES, diff --git a/src/containers/App.js b/src/containers/App.js index 6a92c22..db07627 100644 --- a/src/containers/App.js +++ b/src/containers/App.js @@ -22,7 +22,8 @@ import { ProposalStep3 } from "../presentation/proposal/ProposalStep3"; import { ProposalStep4 } from "../presentation/proposal/ProposalStep4"; import { Values } from "../presentation/values/Values"; import { YourDetails } from "../presentation/YourDetails"; -import { Dev } from "../test/Dev"; +import Dev from "../test/Dev"; +import { AllCollaborations } from "./collaborations/AllCollaborations"; import { CollaborationList } from "./collaborations/CollaborationList"; import { Dashboard } from "./Dashboard"; import HomePage from "./HomePage"; @@ -97,6 +98,19 @@ function App() { path="dashboard" element={} /> + } /> + } + /> + } + /> + } + /> } /> } /> } /> diff --git a/src/containers/collaborations/AllCollaborations.js b/src/containers/collaborations/AllCollaborations.js new file mode 100644 index 0000000..53e4bda --- /dev/null +++ b/src/containers/collaborations/AllCollaborations.js @@ -0,0 +1,131 @@ +import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight"; +import { Avatar, Box, IconButton, Paper, Typography } from "@mui/material"; +import React from "react"; +import { useSearchParams } from "react-router-dom"; +import { collaborations as data, influencers, listings } from "../../api/data"; +import { CollaborationsStateCounts } from "../../presentation/CollaborationsStateCounts"; + +export const AllCollaborations = () => { + const [collaborations, setCollaborations] = React.useState([]); + let [searchParams] = useSearchParams(); + React.useEffect(() => { + setCollaborations( + data.filter((c) => { + let filter = searchParams.get("filter"); + if (filter) { + return c.state.toLowerCase() === filter; + } + + return c; + }) + ); + }, [searchParams]); + + const handleClick = (c) => { + console.log(c); + }; + + return ( + + + {collaborations + .sort((a, b) => { + if (a.state < b.state) return -1; + if (a.state > b.state) return 1; + return 0; + }) + .map((c) => { + const influencer = influencers.find((i) => i.id === c.influencer); + const listing = listings.find((l) => l.id === c.listing); + + return ( + + + + + + {listing.title} + + + {listing.name} + + + + handleClick(c)}> + + + + + + {listing.listingMonth} {listing.listingYear} + + + {c.state} + + + + ); + })} + + ); +}; + +/* +id: uuid(), + listing: listing.id, + state: randomSelection(COLLABORATION_STATES, 1), + application: { + details: faker.random.words(faker.random.numeric(2)), + posts: faker.random.numeric(1), + reels: faker.random.numeric(1, { + bannedDigits: ["4", "5", "6", "7", "8", "9"], + }), + }, + influencer: influencer.id, +*/ diff --git a/src/containers/proposals/AllListings.js b/src/containers/proposals/AllListings.js index 495f5fc..3c64a73 100644 --- a/src/containers/proposals/AllListings.js +++ b/src/containers/proposals/AllListings.js @@ -1,39 +1,26 @@ // import MailIcon from "@mui/icons-material/Mail"; -import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight"; import { - Avatar, // Badge, Box, Button, - IconButton, Paper, Typography, } from "@mui/material"; import React, { useEffect } from "react"; import { useNavigate } from "react-router-dom"; -import { collaborations, listings as data } from "../../api/data"; -import { CollaborationsStateCounts } from "../../presentation/CollaborationsStateCounts"; -const text = { - whiteSpace: "nowrap", - overflow: "hidden", - textOverflow: "ellipsis", - "&>p": { - fontWeight: 600, - "&::first-letter": { - textTransform: "capitalize", - }, - }, -}; +import { listings as data, collaborations as collabs } from "../../api/data"; +import { ListingRow } from "../../presentation/ListingRow"; + export const AllListings = () => { const nav = useNavigate(); const [listings, setListings] = React.useState([]); + const [collaborations, setCollaborations] = React.useState([]); - const handleClick = (listing) => { - nav("/listings/view/" + listing.id); - }; + //TODO: Fixme: this won't be the way an api is called useEffect(() => { setListings(data); + setCollaborations(collabs); }, []); return ( @@ -44,62 +31,38 @@ export const AllListings = () => { My Listings ({listings.length}) - + {listings .sort( (a, b) => Date.parse(`${a.listingMonth} 1, ${a.listingYear}`) - Date.parse(`${b.listingMonth} 1, ${b.listingYear}`) ) - .map((p) => { + .map((listing) => { + const c = collaborations.filter((c) => { + return c.listing === listing.id; + }); + + const counts = groupBy(c, "state"); return ( - - handleClick(p)} - style={{ whiteSpace: "nowrap", marginRight: "10px" }} - > - - - - handleClick(p)} sx={text}> - {p.title} - - handleClick(p)} sx={text}> - {p.name} - - - - - - - {p.listingMonth} {p.listingYear} - - handleClick(p)}> - - - + ); })} @@ -107,3 +70,17 @@ export const AllListings = () => { ); }; + +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/AvartarLabel.js b/src/presentation/AvartarLabel.js new file mode 100644 index 0000000..9878081 --- /dev/null +++ b/src/presentation/AvartarLabel.js @@ -0,0 +1,15 @@ +import { Avatar, Box, Typography } from "@mui/material"; +import React from "react"; + +export const AvartarLabel = ({ src, label }) => { + return ( + + + + + + {label} + + + ); +}; diff --git a/src/presentation/CollaborationStateLink.js b/src/presentation/CollaborationStateLink.js new file mode 100644 index 0000000..9e52822 --- /dev/null +++ b/src/presentation/CollaborationStateLink.js @@ -0,0 +1,21 @@ +import { Typography } from "@mui/material"; +import React from "react"; +import { Link } from "react-router-dom"; + +const CollaborationStateLink = ({ label, count, color, path }) => { + return ( + + {`${label}(${count})`} + + ); +}; + +export default CollaborationStateLink; diff --git a/src/presentation/CollaborationsStateCounts.js b/src/presentation/CollaborationsStateCounts.js index 8b2204b..0532826 100644 --- a/src/presentation/CollaborationsStateCounts.js +++ b/src/presentation/CollaborationsStateCounts.js @@ -3,22 +3,32 @@ import React from "react"; import { Link } from "react-router-dom"; export const CollaborationsStateCounts = (props) => { - const { hideTitle, collaborations, listingId } = props; + const { hideTitle, collaborations, listingId, queryType, active } = props; const theme = useTheme(); - const collaborationActionStyle = { - color: theme.palette.primary.main, + const collaborationActionStyle = (path) => { + return { + color: + active === path + ? theme.palette.active.main + : theme.palette.primary.main, + }; }; const labelStyle = { fontSize: "0.6rem", }; - const baseUrl = `/collaborations/${listingId}`; + const baseUrl = listingId + ? `/collaborations/${listingId}` + : "/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.listing === listingId); + let collabs; + if (listingId) + collabs = collaborations.filter((c) => c.listing === listingId); + else collabs = collaborations; const counts = groupBy(collabs, "state"); setApplied(counts.APPLIED.length); setApproved(counts.APPROVED.length); @@ -28,8 +38,8 @@ export const CollaborationsStateCounts = (props) => { const item = (label, path, count) => { return ( @@ -41,7 +51,7 @@ export const CollaborationsStateCounts = (props) => { }; return ( - + {!hideTitle && ( Collaborations diff --git a/src/presentation/EllipsisTooltip.js b/src/presentation/EllipsisTooltip.js new file mode 100644 index 0000000..fadf317 --- /dev/null +++ b/src/presentation/EllipsisTooltip.js @@ -0,0 +1,36 @@ +import { Box, Tooltip, Typography } from "@mui/material"; +import React from "react"; + +const EllipsisTooltip = ({ label, labelColor, text, fontSize = "1rem" }) => { + return ( + + + + {label}: + + + {text} + + + + ); +}; + +export default EllipsisTooltip; diff --git a/src/presentation/ListingRow.js b/src/presentation/ListingRow.js new file mode 100644 index 0000000..f144c0c --- /dev/null +++ b/src/presentation/ListingRow.js @@ -0,0 +1,102 @@ +import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight"; +import { Avatar, Box, Typography, useTheme } from "@mui/material"; +import React from "react"; +import { useNavigate } from "react-router"; +import CollaborationStateLink from "./CollaborationStateLink"; +import EllipsisTooltip from "./EllipsisTooltip"; + +export const ListingRow = ({ + id, + listingTitle, + productName, + productImage, + month, + year, + appliedCount, + approvedCount, + rejectedCount, +}) => { + const nav = useNavigate(); + + const theme = useTheme(); + const handleClick = () => { + nav("/listings/view/" + id); + }; + return ( + + + + + + + + + + a, p": { fontSize: "0.8rem" } }} + > + + Collaborations: + + + + + + + + + p": { + margin: 0, + padding: 0, + }, + }, + }} + border={0} + > +

{month.slice(0, 3)}

+

{year}

+
+ + + +
+ ); +}; diff --git a/src/test/Dev.js b/src/test/Dev.js index 706e69a..724dabd 100644 --- a/src/test/Dev.js +++ b/src/test/Dev.js @@ -1,21 +1,23 @@ -import { Image } from "../presentation/image/Image"; +import { Paper } from "@mui/material"; +import React from "react"; +import { listings } from "../api/data"; +import { ListingRow } from "../presentation/ListingRow"; -export const Dev = () => { - const data = { - image: undefined, - }; - const handleChange = (event) => { - console.log("DEV: handle change", event); - }; +const Dev = () => { return ( - + + + ); }; + +export default Dev; diff --git a/src/test/collaborationStateLink.test.js b/src/test/collaborationStateLink.test.js new file mode 100644 index 0000000..9de9431 --- /dev/null +++ b/src/test/collaborationStateLink.test.js @@ -0,0 +1,33 @@ +import { render } from "@testing-library/react"; +import { HashRouter } from "react-router-dom"; +import { DevComponent } from "./Dev"; +import underTest from "./underTest"; + +test("should render listing row", () => { + const output = render( + underTest( + user, + + ), + { + wrapper: HashRouter, + } + ); + // output.debug(); +}); + +const user = { + given_name: "given", + family_name: "family", + email: "email@domain.tld", + "custom:usertype": "brand", +};