Skip to content

Commit afda104

Browse files
authored
Merge pull request #19 from LMacPhail/sort-by-winning-likelihood
Sort by winning likelihood
2 parents 21f51a1 + c7a09b7 commit afda104

File tree

16 files changed

+131
-118
lines changed

16 files changed

+131
-118
lines changed

src/components/Header.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ProjectTitle } from "./atoms/ProjectTitle";
33
import { ViewType } from "../data/types";
44
import { SET_VIEW_ACTION } from "../state/actions";
55
import { useDispatch } from "react-redux";
6+
import { SearchInput } from "./filters/SearchInput";
67

78
export const Header: React.FC<{
89
view: "about" | "index";
@@ -15,14 +16,14 @@ export const Header: React.FC<{
1516
return (
1617
<header className="sticky top-0 inset-x-0 flex flex-wrap sm:justify-start sm:flex-nowrap z-[48] w-full bg-white border-b text-sm py-2.5 sm:py-4 md:pl-72 dark:bg-gray-800 dark:border-gray-700">
1718
<nav
18-
className="flex basis-full items-center w-full mx-auto px-4 sm:px-6 md:px-8"
19+
className="flex flex-wrap justify-between flex-row gap-2 basis-full items-center w-full mx-auto px-4 sm:px-6 md:px-8"
1920
aria-label="Global"
2021
>
2122
<div className="mr-5 md:mr-0 md:hidden">
2223
<ProjectTitle />
2324
</div>
2425

25-
<div className="w-full flex items-center justify-end ml-auto sm:justify-between sm:gap-x-3 sm:order-3">
26+
<div className="flex items-center justify-between sm:gap-x-3 sm:order-3">
2627
<div className="flex gap-2">
2728
<button
2829
className={`btn btn-${
@@ -42,6 +43,7 @@ export const Header: React.FC<{
4243
</button>
4344
</div>
4445
</div>
46+
<SearchInput />
4547
</nav>
4648
</header>
4749
);

src/components/Main.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import MPIndex from "./content/MPIndex";
44

55
const Main: React.FC<{ view: "about" | "index" }> = ({ view }) => {
66
return (
7-
<div className="w-full pt-10 px-4 sm:px-6 md:px-8 md:pl-80">
7+
<div className="w-full pt-4 px-4 sm:px-6 md:px-8 md:pl-80">
88
{view === "about" && <About />}
99
{view === "index" && <MPIndex />}
1010
</div>

src/components/atoms/Link.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const TextLink: React.FC<{ children: React.ReactNode; link: string }> = ({
2+
children,
3+
link,
4+
}) => (
5+
<a className="text-link" href={link} target="_blank" rel="noreferrer">
6+
{children}
7+
</a>
8+
);
9+
10+
export default TextLink;

src/components/content/About.tsx

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from "react";
2+
import TextLink from "../atoms/Link";
23

34
const faqs: { question: string; answer: JSX.Element }[] = [
45
{
@@ -131,14 +132,9 @@ const faqs: { question: string; answer: JSX.Element }[] = [
131132
<p>
132133
This tool was made by volunteer researchers from the{" "}
133134
<span>
134-
<a
135-
className="text-link"
136-
href="http://mvmtresearch.org"
137-
target="_blank"
138-
rel="noreferrer"
139-
>
135+
<TextLink link="http://mvmtresearch.org">
140136
Movement Research Unit
141-
</a>
137+
</TextLink>
142138
</span>
143139
. We do practical research in support of social movements and campaign
144140
groups.
@@ -151,25 +147,15 @@ const faqs: { question: string; answer: JSX.Element }[] = [
151147
<p>
152148
There are two ways: you can{" "}
153149
<span>
154-
<a
155-
className="text-link"
156-
href="https://go.mvmtresearch.org/join"
157-
target="_blank"
158-
rel="noreferrer"
159-
>
150+
<TextLink link="https://go.mvmtresearch.org/join">
160151
get involved
161-
</a>
152+
</TextLink>
162153
</span>{" "}
163154
(no research experience necessary) or you can{" "}
164155
<span>
165-
<a
166-
className="text-link"
167-
href="https://donate.stripe.com/bIY6rig2w5ohat24gg"
168-
target="_blank"
169-
rel="noreferrer"
170-
>
156+
<TextLink link="https://donate.stripe.com/bIY6rig2w5ohat24gg">
171157
donate
172-
</a>
158+
</TextLink>
173159
</span>{" "}
174160
to cover our running costs.
175161
</p>

src/components/content/FormattedContent.tsx

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from "react";
22
import { extractLinks } from "../../data/utils/string";
3+
import TextLink from "../atoms/Link";
34

45
export const FormattedContent: React.FC<{
56
subHeader: string;
@@ -21,14 +22,7 @@ export const FormattedContent: React.FC<{
2122
<li key={i}>
2223
{formattedPoint.content}{" "}
2324
{formattedPoint.link?.[0] && (
24-
<a
25-
className="text-link"
26-
href={formattedPoint.link[0]}
27-
target="_blank"
28-
rel="noreferrer"
29-
>
30-
(source)
31-
</a>
25+
<TextLink link={formattedPoint.link[0]}>(source)</TextLink>
3226
)}
3327
</li>
3428
))}
@@ -37,14 +31,7 @@ export const FormattedContent: React.FC<{
3731
<>
3832
{formattedContent[0].content}{" "}
3933
{formattedContent[0].link && formattedContent[0].link.length > 0 && (
40-
<a
41-
className="text-link"
42-
href={formattedContent[0]?.link[0]}
43-
target="_blank"
44-
rel="noreferrer"
45-
>
46-
(source)
47-
</a>
34+
<TextLink link={formattedContent[0]?.link[0]}>(source)</TextLink>
4835
)}
4936
</>
5037
)}

src/components/content/MPIndex.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import React, { useMemo, useState } from "react";
22
import { Accordion } from "./Accordion";
3-
import { filterProfiles } from "../../data/utils/utils";
3+
import { filterProfiles, sortByWin } from "../../data/utils/utils";
44
import { useSelector } from "react-redux";
55
import { AppState } from "../../state/store";
66
import { MP } from "../../data/types";
77
import { Spinner } from "../atoms/Spinner";
8-
import { Filters } from "../filters/Filters";
98

109
const MPIndex: React.FC = () => {
1110
const filters = useSelector((state: AppState) => state.activeFilters);
@@ -14,7 +13,16 @@ const MPIndex: React.FC = () => {
1413
const [mps, setMPs] = useState<MP[]>(filterProfiles(profiles, filters));
1514

1615
useMemo(() => {
17-
setMPs(filterProfiles(profiles, filters));
16+
if (filters.sortDescending !== undefined) {
17+
setMPs(
18+
sortByWin(
19+
filterProfiles(profiles, filters).slice(),
20+
filters.sortDescending
21+
)
22+
);
23+
} else {
24+
setMPs(filterProfiles(profiles, filters));
25+
}
1826
}, [filters, profiles]);
1927

2028
return (
@@ -24,8 +32,7 @@ const MPIndex: React.FC = () => {
2432
<Spinner />
2533
</div>
2634
) : (
27-
<div className="flex flex-col">
28-
<Filters />
35+
<div className="flex flex-col gap-4">
2936
<Accordion mps={mps} />
3037
</div>
3138
)}

src/components/filters/Filters.tsx

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,54 @@
1-
import React from "react";
2-
import { SearchInput } from "../SearchInput";
1+
import React, { useState } from "react";
2+
import { useDispatch } from "react-redux";
3+
import { SET_SORTBY_ACTION } from "../../state/actions";
4+
import TextLink from "../atoms/Link";
35

4-
export const Filters: React.FC = () => {
5-
return (
6-
<div className="">
7-
<SearchInput />
8-
</div>
9-
);
10-
};
11-
12-
// type SelectedSortDirection = "ascending" | "descending";
6+
type SelectedSortDirection = "ascending" | "descending";
7+
const DESCENDING_OPT_TEXT = "Most Likely";
8+
const ASCENDING_OPT_TEXT = "Least Likely";
139

14-
// TODO: Not make this break everything
15-
// const SortByDropdown: React.FC = () => {
16-
// const dispatch = useDispatch();
17-
// const profiles = useSelector((state: AppState) => state.data.profiles);
10+
export const SortByDropdown: React.FC = () => {
11+
const dispatch = useDispatch();
1812

19-
// const [sortDirection, setSortDirection] = useState<
20-
// SelectedSortDirection | undefined
21-
// >(undefined);
13+
const [sortDirection, setSortDirection] = useState<
14+
SelectedSortDirection | undefined
15+
>("descending");
2216

23-
// const handleSelectChange = (value: SelectedSortDirection) => {
24-
// const sortedProfiles = sortByWin(profiles, value === "descending");
25-
// dispatch({
26-
// type: SET_DATA_ACTION,
27-
// payload: { profiles: sortedProfiles, status: "complete" },
28-
// });
29-
// setSortDirection(value);
30-
// };
17+
const handleSelectChange = (value: SelectedSortDirection) => {
18+
dispatch({
19+
type: SET_SORTBY_ACTION,
20+
payload: { descending: value === "descending" },
21+
});
22+
setSortDirection(value);
23+
};
3124

32-
// return (
33-
// <select
34-
// className="select select-ghost-primary"
35-
// value={sortDirection}
36-
// onChange={(event) =>
37-
// handleSelectChange(event.target.value as SelectedSortDirection)
38-
// }
39-
// aria-label="sort profiles"
40-
// >
41-
// {sortDirection === undefined && (
42-
// <option>Sort by chance of winning</option>
43-
// )}
44-
// <option>Most Likely to Win</option>
45-
// <option>Least Likely to Win</option>
46-
// </select>
47-
// );
48-
// };
25+
return (
26+
<div>
27+
<span className="text-xs">
28+
Sort by likeliness to win:{" "}
29+
<TextLink link="https://www.electoralcalculus.co.uk/">
30+
(source)
31+
</TextLink>
32+
</span>
33+
<select
34+
className="select select-ghost-primary select-sm"
35+
value={
36+
sortDirection === "descending"
37+
? DESCENDING_OPT_TEXT
38+
: ASCENDING_OPT_TEXT
39+
}
40+
onChange={(event) =>
41+
handleSelectChange(
42+
event.target.value === DESCENDING_OPT_TEXT
43+
? "descending"
44+
: "ascending"
45+
)
46+
}
47+
aria-label="sort profiles"
48+
>
49+
<option key={"descending"}>{DESCENDING_OPT_TEXT}</option>
50+
<option key={"ascending"}>{ASCENDING_OPT_TEXT}</option>
51+
</select>
52+
</div>
53+
);
54+
};

src/components/SearchInput.tsx renamed to src/components/filters/SearchInput.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import React from "react";
22
import { useDispatch } from "react-redux";
3-
import { SET_SEARCH_INPUT_ACTION } from "../state/actions";
3+
import { SET_SEARCH_INPUT_ACTION } from "../../state/actions";
44

55
export const SearchInput: React.FC = () => {
66
const dispatch = useDispatch();
77
const handleSearchChange = (value: string) => {
88
dispatch({ type: SET_SEARCH_INPUT_ACTION, payload: { value } });
99
};
1010
return (
11-
<>
11+
<div className="max-[300px]:w-auto min-[300px]:min-w-[280px]">
1212
<label htmlFor="icon" className="sr-only">
1313
Search
1414
</label>
@@ -34,6 +34,6 @@ export const SearchInput: React.FC = () => {
3434
onChange={(e) => handleSearchChange(e.currentTarget.value)}
3535
/>
3636
</div>
37-
</>
37+
</div>
3838
);
3939
};

src/components/sidebar/Footer.tsx

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,31 @@
11
import React from "react";
2+
import TextLink from "../atoms/Link";
3+
import { GithubLogo } from "@phosphor-icons/react";
24

3-
// TODO: Make templates for some of these links that get reused
45
export const Footer: React.FC = () => {
56
return (
67
<div className="text-sm flex flex-col gap-2">
78
<div className="divider"></div>
89
<p>
910
Built by volunteers at the{" "}
10-
<a
11-
className="text-link"
12-
href="http://mvmtresearch.org"
13-
target="_blank"
14-
rel="noreferrer"
15-
>
16-
Movement Research Unit.
17-
</a>
11+
<TextLink link="http://mvmtresearch.org">
12+
Movement Research Unit
13+
</TextLink>
14+
.
1815
</p>
1916
<p>Questions or changes: [email protected]</p>
20-
<a
21-
className="text-link"
22-
href="https://donate.stripe.com/bIY6rig2w5ohat24gg"
23-
target="_blank"
24-
rel="noreferrer"
25-
>
17+
<TextLink link="https://donate.stripe.com/bIY6rig2w5ohat24gg">
2618
Support our work.
27-
</a>
28-
<a
29-
className="text-link"
30-
href="https://go.mvmtresearch.org/join"
31-
target="_blank"
32-
rel="noreferrer"
33-
>
34-
Get involved.
35-
</a>
19+
</TextLink>
20+
<TextLink link="https://go.mvmtresearch.org/join">Get involved.</TextLink>
21+
<TextLink link="https://github.com/LMacPhail/labour-mru">
22+
<span className="flex flex-row gap-2 items-center">
23+
Contribute on Github{" "}
24+
<span>
25+
<GithubLogo size={18} />
26+
</span>
27+
</span>
28+
</TextLink>
3629
</div>
3730
);
3831
};

src/components/sidebar/SidebarContent.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from "react";
22
import { ProjectTitle } from "../atoms/ProjectTitle";
33
import { Footer } from "./Footer";
44
import { PolicyStance } from "../filters/PolicyStance";
5+
import { SortByDropdown } from "../filters/Filters";
56

67
export const SidebarContent: React.FC = () => {
78
return (
@@ -10,6 +11,7 @@ export const SidebarContent: React.FC = () => {
1011
<ProjectTitle />
1112
<div className="divider"></div>
1213
</div>
14+
<SortByDropdown />
1315
<PolicyStance />
1416
<Footer />
1517
</div>

0 commit comments

Comments
 (0)