-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #659 from shreyas1434shinde/YouthNet
Issue task PS-3327 :Youth UI fig-ma match
- Loading branch information
Showing
10 changed files
with
527 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import React from "react"; | ||
import { | ||
Card, | ||
CardContent, | ||
Typography, | ||
Box, | ||
Divider, | ||
IconButton, | ||
} from "@mui/material"; | ||
import { ChevronRight } from "@mui/icons-material"; | ||
|
||
// Interfaces | ||
interface Block { | ||
id: number; | ||
name: string; | ||
selectedCount: number; | ||
} | ||
|
||
interface BlockItemProps { | ||
name: string; | ||
selectedCount: number; | ||
onClick: () => void; | ||
} | ||
|
||
interface AssignVillagesProps { | ||
district: string; | ||
blocks: Block[]; | ||
onBlockClick: (block: Block) => void; | ||
} | ||
|
||
// Generic BlockItem Component | ||
const BlockItem: React.FC<BlockItemProps> = ({ name, selectedCount, onClick }) => ( | ||
<Box | ||
display="flex" | ||
justifyContent="space-between" | ||
alignItems="center" | ||
padding={2} | ||
borderRadius={2} | ||
border="1px solid #E0E0E0" | ||
sx={{ | ||
backgroundColor: "#fff", | ||
cursor: "pointer", | ||
marginBottom: 1, | ||
transition: "background-color 0.2s ease", | ||
'&:hover': { backgroundColor: "#f5f5f5" }, | ||
}} | ||
onClick={onClick} | ||
> | ||
<Box> | ||
<Typography variant="body1" fontWeight="bold"> | ||
{name} | ||
</Typography> | ||
<Typography variant="body2" color="textSecondary"> | ||
{selectedCount} villages selected | ||
</Typography> | ||
</Box> | ||
<IconButton size="small" disableRipple> | ||
<ChevronRight /> | ||
</IconButton> | ||
</Box> | ||
); | ||
|
||
// Main Component | ||
const AssignVillages: React.FC<AssignVillagesProps> = ({ district, blocks, onBlockClick }) => { | ||
return ( | ||
<Card sx={{ maxWidth: 400, margin: "auto", padding: 2, boxShadow: 1 }}> | ||
<CardContent> | ||
<Typography variant="h6" gutterBottom> | ||
Assign Villages from Blocks | ||
</Typography> | ||
<Typography variant="body2" color="textSecondary" gutterBottom> | ||
You can complete this later at your own pace. However, the villages will | ||
only be assigned once you click on ‘Finish.’ | ||
</Typography> | ||
<Divider sx={{ marginY: 2 }} /> | ||
<Typography variant="subtitle1" fontWeight="bold" gutterBottom> | ||
{district} District | ||
</Typography> | ||
<Box> | ||
{blocks.map((block) => ( | ||
<BlockItem | ||
key={block.id} | ||
name={block.name} | ||
selectedCount={block.selectedCount} | ||
onClick={() => onBlockClick(block)} | ||
/> | ||
))} | ||
</Box> | ||
</CardContent> | ||
</Card> | ||
); | ||
}; | ||
|
||
// Example Usage | ||
const ExamplePage: React.FC = () => { | ||
const blocks: Block[] = [ | ||
{ id: 1, name: "Ambegaon", selectedCount: 0 }, | ||
{ id: 2, name: "Baramati", selectedCount: 0 }, | ||
{ id: 3, name: "Bhor", selectedCount: 0 }, | ||
{ id: 4, name: "Daund", selectedCount: 0 }, | ||
{ id: 5, name: "Haveli", selectedCount: 0 }, | ||
{ id: 6, name: "Indapur", selectedCount: 0 }, | ||
]; | ||
|
||
const handleBlockClick = (block: Block) => { | ||
console.log("Clicked block:", block); | ||
}; | ||
|
||
return ( | ||
<AssignVillages | ||
district="Pune" | ||
blocks={blocks} | ||
onBlockClick={handleBlockClick} | ||
/> | ||
); | ||
}; | ||
|
||
export default ExamplePage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import React from "react"; | ||
import { | ||
TextField, | ||
RadioGroup, | ||
FormControlLabel, | ||
Radio, | ||
FormLabel, | ||
Box, | ||
} from "@mui/material"; | ||
|
||
interface Field { | ||
type: any; | ||
label: string; | ||
options?: { label: string; value: string }[]; | ||
} | ||
|
||
interface GenericFormProps { | ||
fields: Field[]; | ||
} | ||
|
||
const GenericForm: React.FC<GenericFormProps> = ({ fields }) => { | ||
return ( | ||
<Box | ||
component="form" | ||
sx={{ | ||
maxWidth: 400, | ||
margin: "auto", | ||
display: "flex", | ||
flexDirection: "column", | ||
gap: 2, | ||
padding: 2, | ||
border: "1px solid #ddd", | ||
borderRadius: "8px", | ||
}} | ||
> | ||
{fields.map((field, index) => { | ||
switch (field.type) { | ||
case "text": | ||
case "email": | ||
case "number": | ||
return ( | ||
<TextField | ||
key={index} | ||
label={field.label} | ||
type={field.type} | ||
variant="outlined" | ||
fullWidth | ||
/> | ||
); | ||
case "radio": | ||
return ( | ||
<Box key={index}> | ||
<FormLabel>{field.label}</FormLabel> | ||
<RadioGroup row> | ||
{field.options?.map((option, i) => ( | ||
<FormControlLabel | ||
key={i} | ||
value={option.value} | ||
control={<Radio />} | ||
label={option.label} | ||
/> | ||
))} | ||
</RadioGroup> | ||
</Box> | ||
); | ||
default: | ||
return null; | ||
} | ||
})} | ||
</Box> | ||
); | ||
}; | ||
|
||
export default GenericForm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
"use client"; | ||
|
||
import React, { useState } from "react"; | ||
import { | ||
TextField, | ||
Checkbox, | ||
FormControlLabel, | ||
List, | ||
ListItem, | ||
ListItemText, | ||
ListItemButton, | ||
Paper, | ||
Typography, | ||
IconButton, | ||
Divider, | ||
MenuItem, | ||
Select, | ||
} from "@mui/material"; | ||
import SearchIcon from "@mui/icons-material/Search"; | ||
|
||
const villagesBySection = { | ||
A: ["Ambade", "Angasule", "Apati"], | ||
B: ["Bare", "Bhairavnathnagar", "Bhambatmal"], | ||
C: ["Chikhalavade Kh."], | ||
}; | ||
|
||
const totalVillages = Object.values(villagesBySection).flat().length; | ||
|
||
const VillageSelector = () => { | ||
const [search, setSearch] = useState(""); | ||
const [selected, setSelected] = useState<string[]>([]); | ||
const [sortOrder, setSortOrder] = useState("A-Z"); | ||
|
||
const handleToggle = (village: string) => { | ||
setSelected((prev: string[]) => | ||
prev.includes(village) | ||
? prev.filter((item) => item !== village) | ||
: [...prev, village] | ||
); | ||
}; | ||
|
||
const sortedSections = Object.entries(villagesBySection).reduce( | ||
(acc, [section, villages]) => { | ||
const filteredVillages = villages.filter((village) => | ||
village.toLowerCase().includes(search.toLowerCase()) | ||
); | ||
if (filteredVillages.length) { | ||
acc[section] = sortOrder === "A-Z" ? filteredVillages.sort() : filteredVillages.sort().reverse(); | ||
} | ||
return acc; | ||
}, | ||
{} as Record<string, string[]> | ||
); | ||
|
||
return ( | ||
<Paper sx={{ width: 300, padding: 2 }}> | ||
<Typography variant="h6">Bhor Block</Typography> | ||
<div style={{ display: "flex", alignItems: "center", gap: 1 }}> | ||
<TextField | ||
variant="outlined" | ||
size="small" | ||
placeholder="Search Village.." | ||
value={search} | ||
onChange={(e) => setSearch(e.target.value)} | ||
fullWidth | ||
/> | ||
<IconButton> | ||
<SearchIcon /> | ||
</IconButton> | ||
</div> | ||
<Select | ||
value={sortOrder} | ||
onChange={(e) => setSortOrder(e.target.value)} | ||
fullWidth | ||
size="small" | ||
sx={{ mt: 1, mb: 1 }} | ||
> | ||
<MenuItem value="A-Z">A-Z</MenuItem> | ||
<MenuItem value="Z-A">Z-A</MenuItem> | ||
</Select> | ||
<FormControlLabel | ||
control={<Checkbox />} | ||
label={`Select All (${totalVillages} Villages)`} | ||
onChange={() => | ||
setSelected( | ||
selected.length === totalVillages ? [] : Object.values(villagesBySection).flat() | ||
) | ||
} | ||
checked={selected.length === totalVillages} | ||
/> | ||
{Object.entries(sortedSections).map(([section, villages]) => ( | ||
<div key={section}> | ||
<Typography variant="subtitle1" sx={{ mt: 2, mb: 1 }}> | ||
{section} | ||
</Typography> | ||
<Divider /> | ||
<List> | ||
{villages.map((village) => ( | ||
<ListItem key={village} disablePadding> | ||
<ListItemButton onClick={() => handleToggle(village)}> | ||
<Checkbox checked={selected.includes(village)} /> | ||
<ListItemText primary={village} /> | ||
</ListItemButton> | ||
</ListItem> | ||
))} | ||
</List> | ||
</div> | ||
))} | ||
</Paper> | ||
); | ||
}; | ||
|
||
export default VillageSelector; |
Oops, something went wrong.