3.5 KiB
3.5 KiB
My Activity Page
Overview
File Path: admin/src/pages/volunteer/MyActivityPage.tsx (137 lines)
Route: /volunteer/activity
Role Requirements: Authenticated users
Purpose: Volunteer activity dashboard showing canvassing statistics and visit history.
Key Features:
- Statistics cards (Today's Visits, Total Doors, Total Sessions)
- Outcome breakdown with color-coded tags
- Visit history table (address, outcome, timestamp)
- Pagination (20 visits per page)
- Parallel stats + visits fetch
- Dark theme (VolunteerLayout)
Features
1. Statistics Cards
<Row gutter={16}>
<Col xs={24} sm={8}>
<Card>
<Statistic
title="Today's Visits"
value={stats.todayVisits}
prefix={<CheckCircleOutlined />}
valueStyle={{ color: '#52c41a' }}
/>
</Card>
</Col>
<Col xs={24} sm={8}>
<Card>
<Statistic
title="Total Doors"
value={stats.totalDoors}
prefix={<HomeOutlined />}
valueStyle={{ color: '#1890ff' }}
/>
</Card>
</Col>
<Col xs={24} sm={8}>
<Card>
<Statistic
title="Total Sessions"
value={stats.totalSessions}
prefix={<ClockCircleOutlined />}
valueStyle={{ color: '#722ed1' }}
/>
</Card>
</Col>
</Row>
2. Outcome Breakdown
<Card title="Outcome Breakdown">
<Space wrap>
<Tag color="green">Strong Support: {outcomes.strongSupport}</Tag>
<Tag color="blue">Leaning Support: {outcomes.leaningSupport}</Tag>
<Tag color="yellow">Undecided: {outcomes.undecided}</Tag>
<Tag color="orange">Leaning Opposed: {outcomes.leaningOpposed}</Tag>
<Tag color="red">Opposed: {outcomes.opposed}</Tag>
<Tag color="default">No Answer: {outcomes.noAnswer}</Tag>
<Tag color="gray">Not Home: {outcomes.notHome}</Tag>
</Space>
</Card>
3. Visit History Table
<Table
dataSource={visits}
columns={[
{
title: 'Address',
dataIndex: 'address',
key: 'address'
},
{
title: 'Outcome',
dataIndex: 'outcome',
key: 'outcome',
render: (outcome) => (
<Tag color={getOutcomeColor(outcome)}>
{outcome.replace('_', ' ')}
</Tag>
)
},
{
title: 'Notes',
dataIndex: 'notes',
key: 'notes',
ellipsis: true
},
{
title: 'Time',
dataIndex: 'createdAt',
key: 'createdAt',
render: (date) => dayjs(date).format('MMM D, h:mm A')
}
]}
pagination={{
current: page,
total: total,
pageSize: 20,
onChange: setPage
}}
/>
API Integration
Endpoints
1. Get Stats
GET /api/map/canvass/my-stats
Authorization: Bearer {token}
Response:
{
"todayVisits": 23,
"totalDoors": 187,
"totalSessions": 12,
"outcomes": {
"strongSupport": 45,
"leaningSupport": 32,
"undecided": 28,
"leaningOpposed": 15,
"opposed": 12,
"noAnswer": 38,
"notHome": 17
}
}
2. Get Visit History
GET /api/map/canvass/my-visits?page=1&limit=20
Authorization: Bearer {token}
Response:
{
"visits": [
{
"id": "cm1visit123",
"address": "123 Main St",
"outcome": "strong_support",
"notes": "Very enthusiastic, requested yard sign",
"createdAt": "2025-02-12T14:30:00.000Z"
}
],
"total": 187,
"page": 1
}