Skip to content

Commit

Permalink
Merge branch 'master' into quick-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfauquette committed Jul 8, 2022
2 parents 59b866f + 0c18eb0 commit 85613f5
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 9 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@mui/x-data-grid": "^5.12.2",
"axios": "^0.27.2",
"i18next": "^21.8.10",
"lodash.isequal": "^4.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^11.17.2",
Expand Down
3 changes: 2 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
QuestionsPage,
InsightsPage,
NotFoundPage,
Home,
} from "./pages";
import ResponsiveAppBar from "./components/ResponsiveAppBar";
import DevModeContext from "./contexts/devMode";
Expand All @@ -29,7 +30,7 @@ export default function App() {
<ResponsiveAppBar />
<Routes>
{/* TODO: put a home page for root url */}
<Route path="/" element={<QuestionsPage />} />
<Route path="/" element={<Home />} />
<Route path="/eco-score" element={<EcoScorePage />} />
<Route path="/logos" element={<LogoAnnotationPage />} />
<Route path="/logos/search" element={<LogoSearchPage />} />
Expand Down
51 changes: 49 additions & 2 deletions src/components/QuestionCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import CardContent from "@mui/material/CardContent";
import Typography from "@mui/material/Typography";
import Badge from "@mui/material/Badge";
import Link from "@mui/material/Link";
import Stack from "@mui/material/Stack";
import Chip from "@mui/material/Chip";

import robotoff from "../robotoff";
import { reformatValueTag } from "../utils";
import { getQuestionSearchParams } from "./QuestionFilter";
import { useTranslation } from "react-i18next";

const QuestionCard = (props) => {
const { filterState, imageSrc, title } = props;
const { filterState, imageSrc, title, showFilterResume } = props;
const {
sortByPopularity,
insightType,
Expand All @@ -22,6 +25,8 @@ const QuestionCard = (props) => {
countryFilter,
} = filterState;

const { t } = useTranslation();

const targetUrl = `/questions?${getQuestionSearchParams(filterState)}`;

const [questionNumber, setQuestionNumber] = React.useState("?");
Expand Down Expand Up @@ -67,7 +72,7 @@ const QuestionCard = (props) => {
: "success"
}
>
<Card sx={{ width: 300, height: 350 }}>
<Card sx={{ width: 300, height: 370 }}>
<CardActionArea
component={Link}
disabled={!questionNumber}
Expand All @@ -81,6 +86,48 @@ const QuestionCard = (props) => {
sx={{ objectFit: "contain" }}
/>
<CardContent>
{showFilterResume && (
<Stack direction="row" flexWrap="wrap">
{filterState?.insightType && (
<Chip
size="small"
label={`${t("questions.filters.short_label.value")}: ${
filterState?.insightType
}`}
/>
)}
{filterState?.valueTag && (
<Chip
size="small"
label={`${t("questions.filters.short_label.value")}: ${
filterState?.valueTag
}`}
/>
)}
{filterState?.countryFilter && (
<Chip
size="small"
label={`${t("questions.filters.short_label.country")}: ${
filterState?.countryFilter
}`}
/>
)}
{filterState?.brandFilter && (
<Chip
size="small"
label={`${t("questions.filters.short_label.brand")}: ${
filterState?.brandFilter
}`}
/>
)}
{filterState?.sortByPopularity && (
<Chip
size="small"
label={`${t("questions.filters.short_label.popularity")}`}
/>
)}
</Stack>
)}
<Typography gutterBottom variant="h5" component="div">
{title}
</Typography>
Expand Down
23 changes: 21 additions & 2 deletions src/components/QuestionFilter/QuestionFilter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,22 @@ import RadioGroup from "@mui/material/RadioGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import Box from "@mui/material/Box";
import Radio from "@mui/material/Radio";
import IconButton from "@mui/material/IconButton";

import EditIcon from "@mui/icons-material/Edit";
import StarIcon from "@mui/icons-material/Star";
import StarBorderIcon from "@mui/icons-material/StarBorder";
import { useTranslation } from "react-i18next";

import brands from "../../assets/brands.json";
import { countryNames, insightTypesNames } from "./const";

export const QuestionFilter = ({ filterState, setFilterState }) => {
export const QuestionFilter = ({
filterState,
setFilterState,
isFavorite,
toggleFavorite,
}) => {
const { t } = useTranslation();

const [isOpen, setIsOpen] = React.useState(false);
Expand Down Expand Up @@ -104,7 +112,7 @@ export const QuestionFilter = ({ filterState, setFilterState }) => {
<Box>
{/* Chip indicating the current state of the filtering */}
<Stack direction="row" spacing={1}>
<Stack direction="row" flexWrap="wrap" spacing={1}>
<Stack direction="row" flexWrap="wrap" spacing={1} alignItems="center">
<TextField
select
size="small"
Expand Down Expand Up @@ -159,6 +167,17 @@ export const QuestionFilter = ({ filterState, setFilterState }) => {
}}
/>
)}
<IconButton
onClick={() => {
toggleFavorite();
}}
>
{isFavorite ? (
<StarIcon style={{ color: "gold" }} />
) : (
<StarBorderIcon style={{ color: "gold" }} />
)}
</IconButton>
</Stack>
</Stack>

Expand Down
28 changes: 25 additions & 3 deletions src/components/QuestionFilter/useFilterSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from "react";

import { key2urlParam, DEFAULT_FILTER_STATE } from "./const";
import { useLocation } from "react-router-dom";
import { localFavorites } from "../../localeStorageManager";

export const getQuestionSearchParams = (filterState) => {
const urlParams = new URLSearchParams(window.location.search);
Expand Down Expand Up @@ -40,8 +41,12 @@ const getSearchFromUrl = () => {
export function useFilterSearch() {
const { search } = useLocation();

const [searchParams, setInternSearchParams] = React.useState(() =>
getSearchFromUrl()
const initialParams = getSearchFromUrl();
const [searchParams, setInternSearchParams] = React.useState(
() => initialParams
);
const [isFavorite, setIsFavorite] = React.useState(
localFavorites.isSaved(initialParams)
);

React.useEffect(() => {
Expand All @@ -63,10 +68,27 @@ export function useFilterSearch() {
return;
}

setIsFavorite(localFavorites.isSaved(newState));
setInternSearchParams(newState);
updateSearchSearchParams(newState);
},
[searchParams]
);
return [searchParams, setSearchParams];

const toggleFavorite = React.useCallback(
(imageSrc = "", title = "") => {
const isSaved = localFavorites.isSaved(searchParams);

if (isSaved) {
localFavorites.removeQuestion(searchParams);
} else {
localFavorites.addQuestion(searchParams, imageSrc, title);
}

setIsFavorite(!isSaved);
},
[searchParams]
);

return [searchParams, setSearchParams, isFavorite, toggleFavorite];
}
59 changes: 59 additions & 0 deletions src/localeStorageManager.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import isEqual from "lodash.isequal";

const STORAGE_KEY = "hunger-game-settings";

export const localSettings = {
Expand Down Expand Up @@ -31,3 +33,60 @@ export const getLang = () => {
(navigator.language || navigator.userLanguage).split("-")[0]
);
};

const FAVORITE_STORAGE_KEY = "hunger-game-favorites";

export const localFavorites = {
mem: null,
fetch: function () {
return JSON.parse(localStorage.getItem(FAVORITE_STORAGE_KEY) || "{}");
},
save: function (favorites) {
localStorage.setItem(FAVORITE_STORAGE_KEY, JSON.stringify(favorites));
},
addQuestion: function (filterState, imageSrc, title) {
if (this.mem == null) {
this.mem = this.fetch();
}
if (!this.mem.questions) {
this.mem.questions = [];
}
const questionIndex = this.mem.questions.indexOf(
({ filterState: memFilterState }) => isEqual(memFilterState, filterState)
);
if (questionIndex < 0) {
this.mem.questions.push({ filterState, imageSrc, title });
} else {
this.mem.questions[questionIndex] = { filterState, imageSrc, title };
}
console.log(this.mem);
this.save(this.mem);
},
removeQuestion: function (filterState) {
if (this.mem == null) {
this.mem = this.fetch();
}
if (!this.mem.questions) {
return;
}
this.mem.questions = this.mem.questions.filter(
({ filterState: memFilterState }) => !isEqual(memFilterState, filterState)
);
this.save(this.mem);
},
isSaved: function (filterState) {
if (this.mem == null) {
this.mem = this.fetch();
}

if (!this.mem.questions) {
return false;
}

return (
this.mem.questions.filter(({ filterState: memFilterState }) =>
isEqual(memFilterState, filterState)
).length > 0
);
},
};
29 changes: 29 additions & 0 deletions src/pages/home/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from "react";

import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";

import QuestionCard from "../../components/QuestionCard";
import { localFavorites } from "../../localeStorageManager";

const Home = () => {
const [savedQuestions] = React.useState(() => {
return localFavorites.fetch().questions ?? [];
});

return (
<Box sx={{ p: 2 }}>
<Typography>Home</Typography>
<Stack spacing={4} flexWrap="wrap" direction="row">
{savedQuestions.map((props) => (
<Box sx={{ marginBottom: 5 }} key={props.title}>
<QuestionCard showFilterResume {...props} />
</Box>
))}
</Stack>
</Box>
);
};

export default Home;
1 change: 1 addition & 0 deletions src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { default as EcoScorePage } from "./eco-score";
export { default as SettingsPage } from "./settings";
export { default as QuestionsPage } from "./questions";
export { default as InsightsPage } from "./insights";
export { default as Home } from "./home";
export { default as NotFoundPage } from "./not-found";

export { default as LogoAnnotationPage } from "./logos/LogoAnnotation";
Expand Down
5 changes: 4 additions & 1 deletion src/pages/questions/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import Stack from "@mui/material/Stack";
import Grid from "@mui/material/Grid";

export default function Questions() {
const [filterState, setFilterState] = useFilterSearch();
const [filterState, setFilterState, isFavorite, toggleFavorite] =
useFilterSearch();

const { buffer, answerQuestion, remainingQuestionNb, answers } =
useQuestionBuffer(filterState);
Expand All @@ -25,6 +26,8 @@ export default function Questions() {
<QuestionFilter
filterState={filterState}
setFilterState={setFilterState}
isFavorite={isFavorite}
toggleFavorite={toggleFavorite}
/>
<Divider sx={{ margin: "1rem" }} />
<QuestionDisplay
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6110,6 +6110,11 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==

lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==

lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
Expand Down

0 comments on commit 85613f5

Please sign in to comment.