Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions Projects/Smart Public Issue Reporting System/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 🏙️ Smart Public Issue Reporting System

A responsive Smart Public Issue Reporting System that allows users to report infrastructure and public service issues within their locality, monitor issue status, and maintain a digital record of community concerns.

## Features

- **Issue Reporting Form**: Report new civic issues with title, category, location, priority level, and detailed description.
- **Dynamic Issue Categories**: Categories for Road Damage, Streetlight Failure, Water Leakage, Garbage, Drainage, and more.
- **Issue Dashboard & Stats**: View real-time statistics including Total, Pending, and Resolved issues.
- **Search & Filter**: Search issues by keywords or filter them by their current resolution status.
- **Issue Tracking**: Update issue status (Pending, In Progress, Resolved, Closed) and delete outdated reports.
- **Dark & Light Mode**: Toggle between themes for accessibility, saved locally.
- **Data Persistence**: Uses LocalStorage to safely persist reported issues across sessions.

## How to Run

1. Clone this repository.
2. Navigate to `Projects/smart-public-issue-reporting-system`.
3. Open `index.html` in your web browser.
4. Report a new issue using the form on the left, and watch the dashboard update instantly!

## Technologies Used

- HTML5
- CSS3 (Variables, Grid, Flexbox)
- JavaScript (Vanilla, DOM manipulation, Form Handling, LocalStorage)

## Author

- [MistryVishwa](https://github.com/MistryVishwa)
112 changes: 112 additions & 0 deletions Projects/Smart Public Issue Reporting System/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart Public Issue Reporting System</title>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="app-container">
<header>
<div class="header-content">
<h1>🏙️ Civic Report</h1>
<p>Smart Public Issue Reporting System</p>
</div>
<button id="themeToggle" class="btn-icon" aria-label="Toggle Theme">🌙</button>
</header>

<main class="grid-container">
<!-- Left Column: Report Form -->
<section class="card form-section">
<h2>Report an Issue</h2>
<form id="issueForm">
<div class="form-group">
<label for="issueTitle">Issue Title</label>
<input type="text" id="issueTitle" placeholder="E.g., Large pothole on Main St." required>
</div>

<div class="form-group">
<label for="issueCategory">Category</label>
<select id="issueCategory" required>
<option value="">Select Category</option>
<option value="Road Damage">Road Damage</option>
<option value="Streetlight">Streetlight Failure</option>
<option value="Water Leakage">Water Leakage</option>
<option value="Garbage">Garbage Collection</option>
<option value="Drainage">Drainage Problems</option>
<option value="Other">Other Civic Issues</option>
</select>
</div>

<div class="form-group">
<label for="issueLocation">Location</label>
<input type="text" id="issueLocation" placeholder="Street address or landmark" required>
</div>

<div class="form-group">
<label for="issuePriority">Priority Level</label>
<select id="issuePriority" required>
<option value="Low">Low</option>
<option value="Medium">Medium</option>
<option value="High">High</option>
<option value="Critical">Critical</option>
</select>
</div>

<div class="form-group">
<label for="issueDescription">Description</label>
<textarea id="issueDescription" rows="4" placeholder="Provide more details about the issue..." required></textarea>
</div>

<button type="submit" class="btn-primary">Submit Report</button>
</form>
</section>

<!-- Right Column: Dashboard & Tracking -->
<section class="dashboard-section">
<!-- Stats Overview -->
<div class="stats-grid">
<div class="stat-card">
<span class="stat-value" id="totalIssues">0</span>
<span class="stat-label">Total Reported</span>
</div>
<div class="stat-card">
<span class="stat-value" id="pendingIssues">0</span>
<span class="stat-label">Pending</span>
</div>
<div class="stat-card">
<span class="stat-value" id="resolvedIssues">0</span>
<span class="stat-label">Resolved</span>
</div>
</div>

<!-- Filters -->
<div class="card filters-card">
<div class="filters-row">
<input type="text" id="searchIssue" placeholder="Search issues...">
<select id="filterStatus">
<option value="All">All Statuses</option>
<option value="Pending">Pending</option>
<option value="In Progress">In Progress</option>
<option value="Resolved">Resolved</option>
</select>
</div>
</div>

<!-- Issue List -->
<div class="card issues-container">
<div class="issues-header">
<h2>Recent Reports</h2>
</div>
<div id="issuesList" class="issues-list">
<!-- Issue cards will be injected here via JS -->
</div>
</div>
</section>
</main>
</div>
<script src="script.js"></script>
</body>
</html>
15 changes: 15 additions & 0 deletions Projects/Smart Public Issue Reporting System/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "Smart Public Issue Reporting System",
"description": "Create a responsive Smart Public Issue Reporting System that allows users to report infrastructur...",
"author": {
"name": "MistryVishwa",
"github": "MistryVishwa"
},
"tags": [
"javascript",
"frontend",
"civic-tech",
"dashboard"
],
"entry": "index.html"
}
156 changes: 156 additions & 0 deletions Projects/Smart Public Issue Reporting System/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
document.addEventListener('DOMContentLoaded', () => {
// State management
let issues = JSON.parse(localStorage.getItem('civicIssues')) || [];
const isDarkMode = localStorage.getItem('civicTheme') === 'dark';

// DOM Elements
const themeToggle = document.getElementById('themeToggle');
const issueForm = document.getElementById('issueForm');
const issuesListEl = document.getElementById('issuesList');
const searchInput = document.getElementById('searchIssue');
const filterStatusSelect = document.getElementById('filterStatus');

// Stats Elements
const totalEl = document.getElementById('totalIssues');
const pendingEl = document.getElementById('pendingIssues');
const resolvedEl = document.getElementById('resolvedIssues');

// Init Theme
if (isDarkMode) {
document.body.setAttribute('data-theme', 'dark');
themeToggle.textContent = '☀️';
}

// Save & Render
const saveIssues = () => {
localStorage.setItem('civicIssues', JSON.stringify(issues));
renderDashboard();
};

// Format Date
const formatDate = (dateString) => {
const options = { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute:'2-digit' };
return new Date(dateString).toLocaleDateString(undefined, options);
};

// Form Submit Handler
issueForm.addEventListener('submit', (e) => {
e.preventDefault();

const newIssue = {
id: Date.now().toString(),
title: document.getElementById('issueTitle').value.trim(),
category: document.getElementById('issueCategory').value,
location: document.getElementById('issueLocation').value.trim(),
priority: document.getElementById('issuePriority').value,
description: document.getElementById('issueDescription').value.trim(),
status: 'Pending',
date: new Date().toISOString()
};

issues.unshift(newIssue); // Add to top
saveIssues();
issueForm.reset();
});

// Render Issues
const renderIssuesList = (filteredIssues) => {
issuesListEl.innerHTML = '';

if (filteredIssues.length === 0) {
issuesListEl.innerHTML = `<div class="empty-state">No issues found matching your criteria.</div>`;
return;
}

filteredIssues.forEach(issue => {
const card = document.createElement('div');
card.className = 'issue-card';

card.innerHTML = `
<div class="issue-header">
<div class="issue-title">${issue.title}</div>
<span class="badge badge-priority-${issue.priority}">${issue.priority}</span>
</div>
<div class="issue-meta">
<span>📍 ${issue.location}</span>
<span>🏷️ ${issue.category}</span>
<span>🕒 ${formatDate(issue.date)}</span>
</div>
<div class="issue-desc">${issue.description}</div>
<div class="issue-actions">
<select class="status-select" onchange="updateStatus('${issue.id}', this.value)">
<option value="Pending" ${issue.status === 'Pending' ? 'selected' : ''}>Pending</option>
<option value="In Progress" ${issue.status === 'In Progress' ? 'selected' : ''}>In Progress</option>
<option value="Resolved" ${issue.status === 'Resolved' ? 'selected' : ''}>Resolved</option>
<option value="Closed" ${issue.status === 'Closed' ? 'selected' : ''}>Closed</option>
</select>
<button class="btn-delete" onclick="deleteIssue('${issue.id}')">Delete</button>
</div>
`;
issuesListEl.appendChild(card);
});
};

// Global Action Handlers
window.updateStatus = (id, newStatus) => {
const issue = issues.find(i => i.id === id);
if (issue) {
issue.status = newStatus;
saveIssues();
}
};

window.deleteIssue = (id) => {
if (confirm('Are you sure you want to delete this issue record?')) {
issues = issues.filter(i => i.id !== id);
saveIssues();
}
};

// Search and Filter logic
const getFilteredIssues = () => {
const searchTerm = searchInput.value.toLowerCase();
const statusFilter = filterStatusSelect.value;

return issues.filter(issue => {
const matchesSearch = issue.title.toLowerCase().includes(searchTerm) ||
issue.description.toLowerCase().includes(searchTerm) ||
issue.location.toLowerCase().includes(searchTerm);
const matchesStatus = statusFilter === 'All' || issue.status === statusFilter;

return matchesSearch && matchesStatus;
});
};

// Update Dashboard (Stats & List)
const renderDashboard = () => {
// Update Stats
totalEl.textContent = issues.length;
pendingEl.textContent = issues.filter(i => i.status === 'Pending').length;
resolvedEl.textContent = issues.filter(i => i.status === 'Resolved').length;

// Render List based on filters
renderIssuesList(getFilteredIssues());
};

// Filter Listeners
searchInput.addEventListener('input', () => renderIssuesList(getFilteredIssues()));
filterStatusSelect.addEventListener('change', () => renderIssuesList(getFilteredIssues()));

// Theme Toggle
themeToggle.addEventListener('click', () => {
const isDark = document.body.hasAttribute('data-theme');
if (isDark) {
document.body.removeAttribute('data-theme');
themeToggle.textContent = '🌙';
localStorage.setItem('civicTheme', 'light');
} else {
document.body.setAttribute('data-theme', 'dark');
themeToggle.textContent = '☀️';
localStorage.setItem('civicTheme', 'dark');
}
});

// Initial Render
renderDashboard();
});
Loading
Loading