diff --git a/app/src/App.tsx b/app/src/App.tsx index bdf35b4..ba389b6 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -15,6 +15,7 @@ import { VerifyAccount } from './pages/auth/VerifyAccount'; import { FacultyPost } from './pages/post/FacultyPost'; import { WardenPost } from './pages/post/WardenPost'; import { CentreHeadPost } from './pages/post/CentreHeadPost'; +import { PostView } from './pages/post/PostView'; import { Profile } from './pages/profile/Profile'; import { XENPostView } from './pages/admin/XENPostView'; import { AEPostView } from './pages/admin/AEPostView'; @@ -40,6 +41,7 @@ function App() { } /> } /> } /> + } /> } /> } /> } /> diff --git a/app/src/components/ComplaintCard.tsx b/app/src/components/ComplaintCard.tsx index b78f41f..a423cb8 100644 --- a/app/src/components/ComplaintCard.tsx +++ b/app/src/components/ComplaintCard.tsx @@ -1,9 +1,6 @@ -import { useState } from 'react'; -import { createPortal } from 'react-dom'; +import { useNavigate } from 'react-router-dom'; import { - Zap, Hammer, Trash2, Pencil, X, Check, Calendar, MapPin, BedDouble, - MessageSquare, Wrench, GitBranch, ChevronRight, UserCircle, Clock, - Send, AlertCircle, + Zap, Hammer, Calendar, MapPin, BedDouble, MessageSquare, ChevronRight, } from 'lucide-react'; import { POST_PLACES } from '../constants/models'; @@ -44,14 +41,14 @@ export interface EditForm { interface ComplaintCardProps { post: ComplaintPost; role: Role; - isEditing: boolean; - isBusy: boolean; - editForm: EditForm; - onEditFormChange: (patch: Partial) => void; - onStartEdit: (post: ComplaintPost) => void; - onCancelEdit: () => void; - onSaveEdit: (postId: number) => void; - onDelete: (postId: number) => void; + isEditing?: boolean; + isBusy?: boolean; + editForm?: EditForm; + onEditFormChange?: (patch: Partial) => void; + onStartEdit?: (post: ComplaintPost) => void; + onCancelEdit?: () => void; + onSaveEdit?: (postId: number) => void; + onDelete?: (postId: number) => void; // Called after the author successfully posts a comment, so the parent can // refetch and surface the new comment. onCommentPosted?: () => void; @@ -79,24 +76,10 @@ function statusStyle(s: string): StatusStyle { const STAGES = ['XEN', 'AE', 'JE']; -function isEditWindowExpired(createdAt: string): boolean { - return Date.now() - new Date(createdAt).getTime() >= 30 * 60 * 1000; -} - function formatDate(iso: string) { return new Date(iso).toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' }); } -function formatDateTime(iso: string) { - return new Date(iso).toLocaleString('en-IN', { - day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', - }); -} - -function roleLabel(position: string) { - return position.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()); -} - // ── Type theme ───────────────────────────────────────────────────────────────── function typeTheme(isElectrical: boolean) { @@ -105,362 +88,13 @@ function typeTheme(isElectrical: boolean) { : { cardBg: 'bg-sky-50', accentBar: 'bg-sky-500', headerBg: 'bg-sky-100/70', iconColor: 'text-sky-600', badge: 'bg-sky-200 text-sky-900 border-sky-400', stageDone: 'bg-sky-600 border-sky-600' }; } -// ── Stage tracker ────────────────────────────────────────────────────────────── - -function StageTracker({ stage, theme }: { stage: string; theme: ReturnType }) { - const current = STAGES.indexOf(stage); - return ( -
- -
- {STAGES.map((s, idx) => { - const done = current >= 0 && idx <= current; - const isLast = idx === STAGES.length - 1; - return ( -
- - {s} - - {!isLast && ( -
idx ? theme.stageDone.replace('bg-', 'bg-') : 'bg-gray-300'}`} /> - )} -
- ); - })} -
-
- ); -} - -// ── Edit form ────────────────────────────────────────────────────────────────── - -function EditFormFields({ - editForm, isFaculty, isWarden, onEditFormChange, -}: { - editForm: EditForm; - isFaculty: boolean; - isWarden: boolean; - onEditFormChange: (patch: Partial) => void; -}) { - const inputCls = 'w-full text-sm text-gray-800 bg-white border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-gray-400/40 focus:border-gray-600'; - const labelCls = 'block text-[10px] font-bold uppercase tracking-wider text-gray-500 mb-1'; - return ( -
-
- - onEditFormChange({ title: e.target.value })} className={inputCls} /> -
- {isFaculty && ( -
- - -
- )} - {isWarden && ( -
- - onEditFormChange({ room_number: e.target.value })} className={inputCls} /> -
- )} -
- -