├── generated-icon.png ├── server ├── index.d.ts ├── routes.ts ├── types │ └── incident.type.ts ├── routes │ └── incidentsRouter.ts ├── lib │ └── firebase.ts ├── storage.ts ├── index.ts ├── vite.ts └── app │ └── incidents.ts ├── attached_assets ├── Screenshot 2025-05-01 at 10.26.14.png └── Screenshot 2025-05-01 at 10.33.06.png ├── client ├── src │ ├── components │ │ ├── ui │ │ │ ├── aspect-ratio.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── textarea.tsx │ │ │ ├── label.tsx │ │ │ ├── input.tsx │ │ │ ├── separator.tsx │ │ │ ├── progress.tsx │ │ │ ├── toaster.tsx │ │ │ ├── checkbox.tsx │ │ │ ├── slider.tsx │ │ │ ├── switch.tsx │ │ │ ├── badge.tsx │ │ │ ├── tooltip.tsx │ │ │ ├── hover-card.tsx │ │ │ ├── popover.tsx │ │ │ ├── avatar.tsx │ │ │ ├── radio-group.tsx │ │ │ ├── toggle.tsx │ │ │ ├── scroll-area.tsx │ │ │ ├── alert.tsx │ │ │ ├── resizable.tsx │ │ │ ├── toggle-group.tsx │ │ │ ├── tabs.tsx │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── accordion.tsx │ │ │ ├── input-otp.tsx │ │ │ ├── calendar.tsx │ │ │ ├── breadcrumb.tsx │ │ │ ├── pagination.tsx │ │ │ ├── table.tsx │ │ │ ├── drawer.tsx │ │ │ ├── dialog.tsx │ │ │ ├── sheet.tsx │ │ │ ├── form.tsx │ │ │ ├── alert-dialog.tsx │ │ │ ├── toast.tsx │ │ │ ├── command.tsx │ │ │ ├── navigation-menu.tsx │ │ │ ├── select.tsx │ │ │ ├── data-table.tsx │ │ │ └── carousel.tsx │ │ ├── StatCard.tsx │ │ ├── Layout.tsx │ │ ├── StatusBadge.tsx │ │ ├── SuccessModal.tsx │ │ ├── theme-provider.tsx │ │ ├── MobileDrawer.tsx │ │ ├── Header.tsx │ │ ├── Footer.tsx │ │ └── statistics │ │ │ └── charts.tsx │ ├── api │ │ ├── index.d.ts │ │ └── index.js │ ├── main.tsx │ ├── hooks │ │ ├── use-mobile.tsx │ │ └── use-toast.ts │ ├── pages │ │ ├── not-found.tsx │ │ ├── AdminLogin.tsx │ │ ├── Awareness.tsx │ │ └── IncidentDetails.tsx │ ├── lib │ │ ├── firebase.ts │ │ ├── queryClient.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── App.tsx │ └── index.css └── index.html ├── .gitignore ├── .env.example ├── drizzle.config.ts ├── components.json ├── .github └── workflows │ └── main.yml ├── tsconfig.json ├── vite.config.ts ├── README.md ├── shared └── schema.ts ├── tailwind.config.ts ├── DEPLOYMENT_GUIDE.md ├── package.json ├── ADMIN_SETUP_GUIDE.md └── postcss.config.js /generated-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UvinduBro/Anti-Ragging-Support-System/HEAD/generated-icon.png -------------------------------------------------------------------------------- /server/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "@/types" { 2 | import Incident from "@/types/incident.type"; 3 | export default Incident; 4 | } 5 | -------------------------------------------------------------------------------- /attached_assets/Screenshot 2025-05-01 at 10.26.14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UvinduBro/Anti-Ragging-Support-System/HEAD/attached_assets/Screenshot 2025-05-01 at 10.26.14.png -------------------------------------------------------------------------------- /attached_assets/Screenshot 2025-05-01 at 10.33.06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UvinduBro/Anti-Ragging-Support-System/HEAD/attached_assets/Screenshot 2025-05-01 at 10.33.06.png -------------------------------------------------------------------------------- /client/src/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" 2 | 3 | const AspectRatio = AspectRatioPrimitive.Root 4 | 5 | export { AspectRatio } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .DS_Store 4 | server/public 5 | vite.config.ts.* 6 | *.tar.gz 7 | 8 | # Environment Variables 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | #client 2 | VITE_FIREBASE_API_KEY= 3 | VITE_FIREBASE_PROJECT_ID= 4 | VITE_FIREBASE_APP_ID= 5 | 6 | #server 7 | PORT=9000 8 | FIREBASE_API= 9 | FIREBASE_PROJECT_ID= 10 | FIREBASE_APP_ID= 11 | FIREBASE_STORAGE_BUCKET= 12 | FIREBASE_ATH_DOMAIN= -------------------------------------------------------------------------------- /client/src/api/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@/api' { 2 | interface ApiResponse { 3 | data: T; 4 | status: number; 5 | } 6 | 7 | function apiRequest(method: string, url: string, data?: any, headers?: any): Promise>; 8 | export default apiRequest; 9 | } -------------------------------------------------------------------------------- /client/src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /drizzle.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "drizzle-kit"; 2 | 3 | if (!process.env.DATABASE_URL) { 4 | throw new Error("DATABASE_URL, ensure the database is provisioned"); 5 | } 6 | 7 | export default defineConfig({ 8 | out: "./migrations", 9 | schema: "./shared/schema.ts", 10 | dialect: "postgresql", 11 | dbCredentials: { 12 | url: process.env.DATABASE_URL, 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /server/routes.ts: -------------------------------------------------------------------------------- 1 | import type { Express } from "express"; 2 | import { createServer, type Server } from "http"; 3 | 4 | export async function registerRoutes(app: Express): Promise { 5 | // Static routes to the API can be added here if needed 6 | // All Firebase operations will be done client-side 7 | 8 | const httpServer = createServer(app); 9 | 10 | return httpServer; 11 | } 12 | -------------------------------------------------------------------------------- /client/src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" 4 | 5 | const Collapsible = CollapsiblePrimitive.Root 6 | 7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 8 | 9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 10 | 11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent } 12 | -------------------------------------------------------------------------------- /client/src/api/index.js: -------------------------------------------------------------------------------- 1 | const apiRequest = async (method, url, data, headers = { 2 | "Content-Type": "application/json", 3 | }) => { 4 | const response = await fetch(url, { 5 | method, 6 | body: JSON.stringify(data), 7 | credentials: "include", 8 | headers, 9 | }); 10 | 11 | if (!response.ok) { 12 | throw new Error("Network response was not ok"); 13 | } 14 | return response.json(); 15 | }; 16 | 17 | export default apiRequest; 18 | -------------------------------------------------------------------------------- /server/types/incident.type.ts: -------------------------------------------------------------------------------- 1 | export interface Incident { 2 | id: string; 3 | incidentType: string; 4 | description: string; 5 | location: string; 6 | date: string; 7 | time?: string; 8 | docId: string; 9 | status: string; 10 | createdAt?: Date; 11 | updatedAt?: Date; 12 | contactName?: string; 13 | contactEmail?: string; 14 | contactPhone?: string; 15 | optionalContact?: boolean; 16 | mediaFiles?: File[]; 17 | mediaBase64?: string[]; 18 | } -------------------------------------------------------------------------------- /client/src/components/StatCard.tsx: -------------------------------------------------------------------------------- 1 | interface StatCardProps { 2 | title: string; 3 | value: number; 4 | color: string; 5 | borderColor: string; 6 | } 7 | 8 | const StatCard = ({ title, value, color, borderColor }: StatCardProps) => { 9 | return ( 10 |
11 |

{title}

12 |

{value}

13 |
14 | ); 15 | }; 16 | 17 | export default StatCard; 18 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "client/src/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | } 20 | } -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Auto Deploy to VPS 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v3 15 | 16 | - name: Run deploy.sh on VPS 17 | uses: appleboy/ssh-action@v0.1.6 18 | with: 19 | host: ${{ secrets.SERVER_IP }} 20 | username: ${{ secrets.SERVER_USER }} 21 | key: ${{ secrets.SERVER_SSH_KEY }} 22 | script: | 23 | bash /var/www/Anti-Ragging-Support-System/deploy.sh 24 | -------------------------------------------------------------------------------- /client/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from "react-dom/client"; 2 | import App from "./App"; 3 | import "./index.css"; 4 | import { QueryClientProvider } from "@tanstack/react-query"; 5 | import { queryClient } from "./lib/queryClient"; 6 | import { TooltipProvider } from "@/components/ui/tooltip"; 7 | import { Toaster } from "@/components/ui/toaster"; 8 | 9 | createRoot(document.getElementById("root")!).render( 10 | 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /client/src/hooks/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["client/src/**/*", "shared/**/*", "server/**/*"], 3 | "exclude": ["node_modules", "build", "dist", "**/*.test.ts"], 4 | "compilerOptions": { 5 | "incremental": true, 6 | "tsBuildInfoFile": "./node_modules/typescript/tsbuildinfo", 7 | "noEmit": true, 8 | "module": "ESNext", 9 | "strict": true, 10 | "lib": ["esnext", "dom", "dom.iterable"], 11 | "jsx": "preserve", 12 | "esModuleInterop": true, 13 | "skipLibCheck": true, 14 | "allowImportingTsExtensions": true, 15 | "moduleResolution": "bundler", 16 | "baseUrl": ".", 17 | "types": ["node", "vite/client"], 18 | "paths": { 19 | "@/*": ["./client/src/*"], 20 | "@shared/*": ["./shared/*"] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /client/src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Textarea = React.forwardRef< 6 | HTMLTextAreaElement, 7 | React.ComponentProps<"textarea"> 8 | >(({ className, ...props }, ref) => { 9 | return ( 10 |