diff --git a/Projects/Smart Public Issue Reporting System/README.md b/Projects/Smart Public Issue Reporting System/README.md new file mode 100644 index 0000000..734a7c5 --- /dev/null +++ b/Projects/Smart Public Issue Reporting System/README.md @@ -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) diff --git a/Projects/Smart Public Issue Reporting System/index.html b/Projects/Smart Public Issue Reporting System/index.html new file mode 100644 index 0000000..0633dd3 --- /dev/null +++ b/Projects/Smart Public Issue Reporting System/index.html @@ -0,0 +1,112 @@ + + + + + + Smart Public Issue Reporting System + + + + +
+
+
+

🏙️ Civic Report

+

Smart Public Issue Reporting System

+
+ +
+ +
+ +
+

Report an Issue

+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+ + +
+ +
+
+ 0 + Total Reported +
+
+ 0 + Pending +
+
+ 0 + Resolved +
+
+ + +
+
+ + +
+
+ + +
+
+

Recent Reports

+
+
+ +
+
+
+
+
+ + + diff --git a/Projects/Smart Public Issue Reporting System/project.json b/Projects/Smart Public Issue Reporting System/project.json new file mode 100644 index 0000000..57659ea --- /dev/null +++ b/Projects/Smart Public Issue Reporting System/project.json @@ -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" +} diff --git a/Projects/Smart Public Issue Reporting System/script.js b/Projects/Smart Public Issue Reporting System/script.js new file mode 100644 index 0000000..89fbc69 --- /dev/null +++ b/Projects/Smart Public Issue Reporting System/script.js @@ -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 = `
No issues found matching your criteria.
`; + return; + } + + filteredIssues.forEach(issue => { + const card = document.createElement('div'); + card.className = 'issue-card'; + + card.innerHTML = ` +
+
${issue.title}
+ ${issue.priority} +
+
+ 📍 ${issue.location} + 🏷️ ${issue.category} + 🕒 ${formatDate(issue.date)} +
+
${issue.description}
+
+ + +
+ `; + 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(); +}); diff --git a/Projects/Smart Public Issue Reporting System/style.css b/Projects/Smart Public Issue Reporting System/style.css new file mode 100644 index 0000000..21cfaf1 --- /dev/null +++ b/Projects/Smart Public Issue Reporting System/style.css @@ -0,0 +1,326 @@ +:root { + /* Light Theme Colors */ + --primary-color: #0ea5e9; + --primary-hover: #0284c7; + --bg-color: #f1f5f9; + --card-bg: #ffffff; + --text-main: #0f172a; + --text-muted: #64748b; + --border-color: #e2e8f0; + + /* Status Colors */ + --status-pending: #f59e0b; + --status-progress: #3b82f6; + --status-resolved: #10b981; + + /* Priority Colors */ + --priority-low: #10b981; + --priority-medium: #f59e0b; + --priority-high: #ef4444; + --priority-critical: #991b1b; + + --shadow-sm: 0 1px 3px rgba(0,0,0,0.1); + --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1); + --radius-md: 12px; + --radius-lg: 16px; +} + +[data-theme="dark"] { + --primary-color: #38bdf8; + --primary-hover: #0ea5e9; + --bg-color: #0f172a; + --card-bg: #1e293b; + --text-main: #f8fafc; + --text-muted: #94a3b8; + --border-color: #334155; + --shadow-sm: 0 1px 3px rgba(0,0,0,0.5); + --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.5); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Inter', sans-serif; + background-color: var(--bg-color); + color: var(--text-main); + line-height: 1.5; + transition: background-color 0.3s ease, color 0.3s ease; +} + +.app-container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +/* Header */ +header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 30px; +} + +.header-content h1 { + font-size: 2rem; + font-weight: 700; + color: var(--primary-color); +} + +.header-content p { + color: var(--text-muted); + font-weight: 500; +} + +.btn-icon { + background: var(--card-bg); + border: 1px solid var(--border-color); + color: var(--text-main); + width: 44px; + height: 44px; + border-radius: 50%; + font-size: 1.2rem; + cursor: pointer; + box-shadow: var(--shadow-sm); + transition: transform 0.2s, background-color 0.3s; +} + +.btn-icon:hover { + transform: translateY(-2px); +} + +/* Layout */ +.grid-container { + display: grid; + grid-template-columns: 350px 1fr; + gap: 25px; +} + +.card { + background: var(--card-bg); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + padding: 25px; + border: 1px solid var(--border-color); +} + +/* Form Section */ +.form-section h2 { + margin-bottom: 20px; + font-size: 1.25rem; +} + +.form-group { + margin-bottom: 15px; +} + +.form-group label { + display: block; + margin-bottom: 6px; + font-size: 0.9rem; + font-weight: 600; + color: var(--text-muted); +} + +input, select, textarea { + width: 100%; + padding: 10px 12px; + border-radius: var(--radius-md); + border: 1px solid var(--border-color); + background-color: var(--bg-color); + color: var(--text-main); + font-family: inherit; + font-size: 0.95rem; + transition: border-color 0.2s; +} + +input:focus, select:focus, textarea:focus { + outline: none; + border-color: var(--primary-color); +} + +.btn-primary { + width: 100%; + padding: 12px; + background-color: var(--primary-color); + color: #fff; + border: none; + border-radius: var(--radius-md); + font-size: 1rem; + font-weight: 600; + cursor: pointer; + transition: background-color 0.2s; + margin-top: 10px; +} + +.btn-primary:hover { + background-color: var(--primary-hover); +} + +/* Dashboard Section */ +.stats-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 15px; + margin-bottom: 25px; +} + +.stat-card { + background: var(--card-bg); + padding: 20px; + border-radius: var(--radius-lg); + box-shadow: var(--shadow-sm); + text-align: center; + border: 1px solid var(--border-color); +} + +.stat-value { + display: block; + font-size: 2rem; + font-weight: 700; + color: var(--primary-color); +} + +.stat-label { + font-size: 0.9rem; + font-weight: 600; + color: var(--text-muted); +} + +.filters-card { + padding: 15px 25px; + margin-bottom: 25px; +} + +.filters-row { + display: flex; + gap: 15px; +} + +/* Issues List */ +.issues-container { + padding: 20px; + min-height: 400px; +} + +.issues-header h2 { + font-size: 1.2rem; + margin-bottom: 15px; + border-bottom: 1px solid var(--border-color); + padding-bottom: 10px; +} + +.issues-list { + display: flex; + flex-direction: column; + gap: 15px; + max-height: 600px; + overflow-y: auto; + padding-right: 5px; +} + +.issues-list::-webkit-scrollbar { + width: 6px; +} +.issues-list::-webkit-scrollbar-thumb { + background: var(--border-color); + border-radius: 3px; +} + +.issue-card { + background: var(--bg-color); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 15px; + position: relative; +} + +.issue-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 8px; +} + +.issue-title { + font-weight: 600; + font-size: 1.1rem; + margin-bottom: 4px; +} + +.badge { + padding: 4px 8px; + border-radius: 20px; + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; +} + +/* Dynamic Badge Colors handled in JS via data attributes, but we can set bases here */ +.badge-priority-Low { background: rgba(16, 185, 129, 0.15); color: var(--priority-low); } +.badge-priority-Medium { background: rgba(245, 158, 11, 0.15); color: var(--priority-medium); } +.badge-priority-High { background: rgba(239, 68, 68, 0.15); color: var(--priority-high); } +.badge-priority-Critical { background: rgba(153, 27, 27, 0.15); color: var(--priority-critical); } + +.issue-meta { + display: flex; + gap: 15px; + font-size: 0.85rem; + color: var(--text-muted); + margin-bottom: 10px; +} + +.issue-desc { + font-size: 0.95rem; + margin-bottom: 15px; +} + +.issue-actions { + display: flex; + justify-content: space-between; + align-items: center; + border-top: 1px solid var(--border-color); + padding-top: 10px; +} + +.status-select { + width: auto; + padding: 6px 10px; + font-size: 0.85rem; +} + +.btn-delete { + background: none; + border: none; + color: var(--priority-high); + cursor: pointer; + font-size: 0.9rem; + font-weight: 600; +} + +.btn-delete:hover { + text-decoration: underline; +} + +.empty-state { + text-align: center; + color: var(--text-muted); + padding: 40px 0; +} + +/* Responsive */ +@media (max-width: 900px) { + .grid-container { + grid-template-columns: 1fr; + } + .stats-grid { + grid-template-columns: 1fr; + } + .filters-row { + flex-direction: column; + } +}