Skip to content

Commit e08623c

Browse files
authored
Merge pull request wevote#4618 from zohakhan-wevote/WV-2264_Claim_Profile_Add_UI_for_savi_ngPolitical_Party
WV-2264 Claim Profile: Add UI for saving Political Party [IN PROGRESS]
2 parents 8dc7353 + f70d8d0 commit e08623c

2 files changed

Lines changed: 142 additions & 0 deletions

File tree

src/js/components/Drawers/PoliticianSelfEditDrawer.jsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import SettingsSectionFooter from '../Navigation/SettingsSectionFooter';
1717
import SettingsLinks from '../PoliticianSelfEdit/SettingsLinks';
1818
import SettingsNameAndPhoto from '../PoliticianSelfEdit/SettingsNameAndPhoto';
1919
import SettingsOfficialStatement from '../PoliticianSelfEdit/SettingsOfficialStatement';
20+
import SettingsPoliticalParty from '../PoliticianSelfEdit/SettingsPoliticalParty';
2021
import SettingsNotifications from '../Settings/SettingsNotifications';
2122
import { NavLinksContainer } from '../Style/drawerLayoutStyles';
2223
import DrawerTemplateHeaderProfile from './DrawerTemplateHeaderProfile';
@@ -66,6 +67,16 @@ const PoliticianSelfEditDrawer = () => {
6667
linkName: 'teamAccess',
6768
linkTextJsx: <LinkSpan $isActive={String(displayProfileOption) === 'teamAccess'}>Team Access</LinkSpan>,
6869
},
70+
{
71+
icon: <AccountCircle $isActive={String(displayProfileOption) === 'party'} />,
72+
linkName: 'party',
73+
linkTextJsx: (
74+
<LinkSpan $isActive={String(displayProfileOption) === 'party'}>
75+
Political Party
76+
</LinkSpan>
77+
),
78+
},
79+
6980
];
7081

7182
// useEffect to handle which component to display from nav
@@ -104,6 +115,15 @@ const PoliticianSelfEditDrawer = () => {
104115
</>
105116
);
106117
break;
118+
case 'party':
119+
component = (
120+
<SettingsPoliticalParty
121+
externalUniqueId="politicianSelfEditDrawer"
122+
politicianWeVoteId={politicianWeVoteId}
123+
/>
124+
);
125+
break;
126+
107127
default:
108128
// console.log('In PoliticianSelfEditDrawer useEffect default case');
109129
if (!displayProfileOption) {
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import React, { useState } from 'react';
2+
import styled from 'styled-components';
3+
import DesignTokenColors from '../../common/components/Style/DesignTokenColors';
4+
5+
const SettingsPoliticalParty = () => {
6+
const partyOptions = [
7+
"Democratic Party",
8+
"Republican Party",
9+
"Green Party",
10+
"Libertarian Party",
11+
"Independent",
12+
"Enter your own"
13+
];
14+
15+
const [selectedParty, setSelectedParty] = useState("");
16+
const [customParty, setCustomParty] = useState("");
17+
18+
return (
19+
<Wrapper>
20+
<HeaderContainer>
21+
<h1 className="h2">Political Party</h1>
22+
</HeaderContainer>
23+
24+
<Label id="partyLabel" htmlFor="politicalPartySelect">
25+
Select your political party or enter your own below.
26+
</Label>
27+
28+
<Select
29+
id="politicalPartySelect"
30+
aria-labelledby="partyLabel"
31+
value={selectedParty}
32+
onChange={(e) => setSelectedParty(e.target.value)}
33+
>
34+
35+
<option value="">Select party</option>
36+
{partyOptions.map((party) => (
37+
<option key={party} value={party}>
38+
{party}
39+
</option>
40+
))}
41+
</Select>
42+
43+
{/* Custom input only visible if needed */}
44+
{selectedParty === "Enter your own" && (
45+
<CustomWrapper>
46+
<Input
47+
id="customPartyInput"
48+
type="text"
49+
value={customParty}
50+
placeholder="Type your party name..."
51+
aria-label="Type your political party name"
52+
onChange={(e) => setCustomParty(e.target.value)}
53+
/>
54+
</CustomWrapper>
55+
)}
56+
</Wrapper>
57+
);
58+
};
59+
60+
const Wrapper = styled('div')`
61+
padding: 16px;
62+
max-width: 700px;
63+
color: ${DesignTokenColors.neutralUI900};
64+
`;
65+
66+
/* Matches Official Statement header container */
67+
const HeaderContainer = styled('div')`
68+
display: flex;
69+
align-items: center;
70+
margin-bottom: 4px;
71+
`;
72+
73+
/* Uses the same spacing behavior as IntroductionWrapper in Official Statement */
74+
const Label = styled('label')`
75+
display: block;
76+
margin-top: 8px; /* Spacing between title and intro text */
77+
margin-bottom: 12px; /* Same spacing as Official Statement intro text */
78+
font-size: 15px;
79+
color: ${DesignTokenColors.neutralUI700};
80+
font-weight: 600;
81+
`;
82+
83+
const Select = styled('select')`
84+
width: 100%;
85+
padding: 12px;
86+
font-size: 16px;
87+
88+
border-radius: 8px;
89+
border: 1px solid ${DesignTokenColors.neutralUI400};
90+
background-color: ${DesignTokenColors.whiteUI};
91+
color: ${DesignTokenColors.neutralUI900};
92+
93+
appearance: none;
94+
background-image: url("data:image/svg+xml;utf8,<svg fill='%23666' height='24' width='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/></svg>");
95+
background-position: right 12px center;
96+
background-repeat: no-repeat;
97+
98+
&:focus {
99+
border-color: ${DesignTokenColors.primary600};
100+
box-shadow: 0 0 0 2px ${DesignTokenColors.primary200};
101+
}
102+
`;
103+
104+
const Input = styled('input')`
105+
width: 100%;
106+
padding: 12px;
107+
margin-top: 8px;
108+
font-size: 16px;
109+
border-radius: 8px;
110+
border: 1px solid ${DesignTokenColors.neutralUI400};
111+
outline: none;
112+
113+
&:focus {
114+
border-color: ${DesignTokenColors.primary600};
115+
}
116+
`;
117+
118+
const CustomWrapper = styled('div')`
119+
margin-top: 20px;
120+
`;
121+
122+
export default SettingsPoliticalParty;

0 commit comments

Comments
 (0)