Updated all the files with fixes and feature completion for the proof of

concept.
This commit is contained in:
sherlock 2025-04-14 19:22:39 +05:30
parent 9d58cb1d01
commit 7ba3ddb818
5 changed files with 508 additions and 71 deletions

View file

@ -1,4 +1,6 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
# SDT Assignment - Sem IV
This is a module made for demoing the form selection tool for a PIL filer utility for helping with SDG 16: Peace, Justice, and Strong Institutions.
## Getting Started
@ -19,18 +21,3 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

View file

@ -11,6 +11,7 @@
"@radix-ui/react-slot": "^1.2.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"jspdf": "^3.0.1",
"lucide-react": "^0.487.0",
"next": "15.3.0",
"react": "^19.0.0",
@ -36,6 +37,8 @@
"packages": {
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
"@babel/runtime": ["@babel/runtime@7.27.0", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw=="],
"@emnapi/core": ["@emnapi/core@1.4.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.1", "tslib": "^2.4.0" } }, "sha512-H+N/FqT07NmLmt6OFFtDfwe8PNygprzBikrEMyQfgqSmT0vzE515Pz7R8izwB9q/zsH/MA64AKoul3sA6/CzVg=="],
"@emnapi/runtime": ["@emnapi/runtime@1.4.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw=="],
@ -204,10 +207,14 @@
"@types/node": ["@types/node@20.17.30", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg=="],
"@types/raf": ["@types/raf@3.4.3", "", {}, "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw=="],
"@types/react": ["@types/react@19.1.0", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w=="],
"@types/react-dom": ["@types/react-dom@19.1.2", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw=="],
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.29.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.29.1", "@typescript-eslint/type-utils": "8.29.1", "@typescript-eslint/utils": "8.29.1", "@typescript-eslint/visitor-keys": "8.29.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg=="],
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.29.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.29.1", "@typescript-eslint/types": "8.29.1", "@typescript-eslint/typescript-estree": "8.29.1", "@typescript-eslint/visitor-keys": "8.29.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg=="],
@ -286,6 +293,8 @@
"async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
"atob": ["atob@2.1.2", "", { "bin": { "atob": "bin/atob.js" } }, "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="],
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
"axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="],
@ -294,10 +303,14 @@
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"base64-arraybuffer": ["base64-arraybuffer@1.0.2", "", {}, "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="],
"brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"btoa": ["btoa@1.2.1", "", { "bin": { "btoa": "bin/btoa.js" } }, "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g=="],
"busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
@ -310,6 +323,8 @@
"caniuse-lite": ["caniuse-lite@1.0.30001713", "", {}, "sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q=="],
"canvg": ["canvg@3.0.11", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@types/raf": "^3.4.0", "core-js": "^3.8.3", "raf": "^3.4.1", "regenerator-runtime": "^0.13.7", "rgbcolor": "^1.0.1", "stackblur-canvas": "^2.0.0", "svg-pathdata": "^6.0.3" } }, "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA=="],
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
@ -328,8 +343,12 @@
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
"core-js": ["core-js@3.41.0", "", {}, "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
"css-line-break": ["css-line-break@2.1.0", "", { "dependencies": { "utrie": "^1.0.2" } }, "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="],
@ -352,6 +371,8 @@
"doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
"dompurify": ["dompurify@3.2.5", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ=="],
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
@ -420,6 +441,8 @@
"fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="],
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
@ -472,6 +495,8 @@
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
"html2canvas": ["html2canvas@1.4.1", "", { "dependencies": { "css-line-break": "^2.1.0", "text-segmentation": "^1.0.3" } }, "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA=="],
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
@ -552,6 +577,8 @@
"json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
"jspdf": ["jspdf@3.0.1", "", { "dependencies": { "@babel/runtime": "^7.26.7", "atob": "^2.1.2", "btoa": "^1.2.1", "fflate": "^0.8.1" }, "optionalDependencies": { "canvg": "^3.0.11", "core-js": "^3.6.0", "dompurify": "^3.2.4", "html2canvas": "^1.0.0-rc.5" } }, "sha512-qaGIxqxetdoNnFQQXxTKUD9/Z7AloLaw94fFsOiJMxbfYdBbrBuhWmbzI8TVjrw7s3jBY1PFHofBKMV/wZPapg=="],
"jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
@ -642,6 +669,8 @@
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
"performance-now": ["performance-now@2.1.0", "", {}, "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
@ -658,6 +687,8 @@
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
"raf": ["raf@3.4.1", "", { "dependencies": { "performance-now": "^2.1.0" } }, "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA=="],
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
@ -668,6 +699,8 @@
"reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
"regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="],
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
"resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="],
@ -678,6 +711,8 @@
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
"rgbcolor": ["rgbcolor@1.0.1", "", {}, "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw=="],
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
"safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
@ -716,6 +751,8 @@
"stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="],
"stackblur-canvas": ["stackblur-canvas@2.7.0", "", {}, "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ=="],
"streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
"string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="],
@ -740,12 +777,16 @@
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
"svg-pathdata": ["svg-pathdata@6.0.3", "", {}, "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw=="],
"tailwind-merge": ["tailwind-merge@3.2.0", "", {}, "sha512-FQT/OVqCD+7edmmJpsgCsY820RTD5AkBryuG5IUqR5YQZSdj5xlH5nLgH7YPths7WsLPSpSBNneJdM8aS8aeFA=="],
"tailwindcss": ["tailwindcss@4.1.3", "", {}, "sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g=="],
"tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="],
"text-segmentation": ["text-segmentation@1.0.3", "", { "dependencies": { "utrie": "^1.0.2" } }, "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw=="],
"tinyglobby": ["tinyglobby@0.2.12", "", { "dependencies": { "fdir": "^6.4.3", "picomatch": "^4.0.2" } }, "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
@ -778,6 +819,8 @@
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
"utrie": ["utrie@1.0.2", "", { "dependencies": { "base64-arraybuffer": "^1.0.2" } }, "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw=="],
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
"which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
@ -794,6 +837,8 @@
"zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="],
"@babel/runtime/regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="],
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="],

View file

@ -16,6 +16,7 @@
"@radix-ui/react-slot": "^1.2.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"jspdf": "^3.0.1",
"lucide-react": "^0.487.0",
"next": "15.3.0",
"react": "^19.0.0",

445
src/app/file-pil/page.tsx Normal file
View file

@ -0,0 +1,445 @@
"use client";
import React, { useState } from "react";
import Link from "next/link";
import { useForm, useFieldArray } from "react-hook-form";
import { Button } from "@/components/ui/button";
import {
Form,
FormItem,
FormLabel,
FormDescription,
FormMessage,
} from "@/components/ui/form";
// Sample Indian lawyers/orgs
const LAWYERS = [
{ label: "Adv. Rohan Deshmukh (Mumbai)", value: "rohan-deshmukh" },
{ label: "Adv. Priya Nair (Delhi)", value: "priya-nair" },
{ label: "People's Justice Foundation", value: "peoples-justice" },
{ label: "Adv. Anil Kumar Choudhary (Kolkata)", value: "anil-choudhary" },
{ label: "Society for Legal Aid Trust", value: "legal-aid-society" },
];
function downloadMarkdown(filename: string, text: string) {
const blob = new Blob([text], { type: "text/markdown" });
const elem = document.createElement("a");
elem.href = URL.createObjectURL(blob);
elem.download = filename;
elem.click();
}
// --- PDF rendering utilities using jsPDF ---
// Optionally install: npm i jspdf
// And "import jsPDF from 'jspdf';"
let jsPDF: any = null;
if (typeof window !== "undefined") {
// @ts-ignore
import("jspdf").then((mod) => (jsPDF = mod.default));
}
function createMarkdownFromForm(data: any, fileList: File[] = []) {
const lawyer = LAWYERS.find((l) => l.value === data.lawyer)?.label ?? "";
const docsSection =
fileList.length === 0
? "_No files uploaded_"
: fileList.map((f) => `- ${f.name}`).join("\n");
const str = `# Public Interest Litigation (Draft)
**Filed by:** ${lawyer}
---
## 1. Aggrieved Parties
${data.aggrieved
.map(
(p: any, idx: number) =>
`${idx + 1}. **${p.name}**\n - Address: ${p.address}`,
)
.join("\n")}
---
## 2. Respondent Government Agencies
${data.government
.map(
(a: any, idx: number) =>
`${idx + 1}. **${a.name}**\n - Address: ${a.address}`,
)
.join("\n")}
---
## 3. Facts Leading To Violation of Fundamental Rights
${data.facts}
- **Period:** ${data.dates}
- **Prayers/Relief Sought:**
${data.prayers}
${data.precedence ? `**Precedents Cited:** ${data.precedence}\n` : ""}
${data.comments ? `**Extra Comments:** ${data.comments}\n` : ""}
---
## 4. Documents Submitted
${docsSection}
`;
return str;
}
async function createAndDownloadPDF(markdown: string, filename: string) {
if (!jsPDF) {
alert(
"PDF library is still loading. Please try again in a second, or try refreshing.",
);
return;
}
// Preprocess markdown: convert to text with basic formatting
const mdToText = (md: string) =>
md
.replace(/^#+\s?/gm, "") // strip markdown headers
.replace(/\*\*(.+?)\*\*/g, "$1") // bold
.replace(/^- /gm, "• ")
.replace(/_{1,2}(.+?)_{1,2}/g, "$1")
.replace(/\r?\n/g, "\n");
const text = mdToText(markdown);
const doc = new jsPDF();
const lines = doc.splitTextToSize(text, 180);
doc.setFont("helvetica", "normal");
doc.setFontSize(11);
let y = 18;
doc.text(filename.replace(/\.pdf$/i, ""), 10, 10, { maxWidth: 180 });
lines.forEach((line: string) => {
if (y > 285) {
doc.addPage();
y = 10;
}
doc.text(line, 10, y);
y += 7;
});
doc.save(filename);
}
export default function FilePILPage() {
const [output, setOutput] = useState<string | null>(null);
const [uploadedFiles, setUploadedFiles] = useState<File[]>([]);
const form = useForm({
defaultValues: {
lawyer: "",
aggrieved: [{ name: "", address: "" }],
government: [{ name: "", address: "" }],
facts: "",
dates: "",
prayers: "",
comments: "",
precedence: "",
},
});
const { control, register, handleSubmit, reset, formState } = form;
const {
fields: aggrievedFields,
append: appendAggrieved,
remove: removeAggrieved,
} = useFieldArray({ control, name: "aggrieved" });
const {
fields: govFields,
append: appendGovernment,
remove: removeGovernment,
} = useFieldArray({ control, name: "government" });
const onSubmit = (data: any) => {
const md = createMarkdownFromForm(data, uploadedFiles);
setOutput(md);
downloadMarkdown("PIL-draft.md", md);
};
const onRenderPdf = () => {
if (!output) return;
createAndDownloadPDF(output, "PIL-draft.pdf");
};
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
setUploadedFiles(Array.from(e.target.files));
}
};
return (
<div className="min-h-screen flex flex-col font-sans antialiased">
<header className="py-4 px-8 border-b bg-background sticky top-0 z-10">
<div className="flex items-center justify-between max-w-2xl mx-auto">
<span className="font-bold text-lg text-primary">🧑🏽 PIL Filing</span>
<Link
href="/"
className="text-primary-foreground bg-primary px-3 py-1.5 rounded hover:opacity-90 text-sm"
>
Home
</Link>
</div>
</header>
<main className="flex-1 flex justify-center items-start py-6 px-2 bg-muted/10">
<div className="w-full max-w-2xl bg-background rounded shadow-sm px-6 py-8 border">
<h1 className="text-2xl font-bold mb-4 text-center">
Draft & Submit PIL
</h1>
<Form {...form}>
<form
className="space-y-6"
onSubmit={handleSubmit(onSubmit)}
autoComplete="off"
>
{/* 1. Lawyer Selection */}
<FormItem>
<FormLabel>
Choose Public Interest Lawyer/Organization
</FormLabel>
<select
className="w-full border rounded px-3 py-2 bg-background"
{...register("lawyer", { required: "Choose a lawyer" })}
defaultValue=""
>
<option value="" disabled>
Select a Lawyer/Org
</option>
{LAWYERS.map((law) => (
<option key={law.value} value={law.value}>
{law.label}
</option>
))}
</select>
{formState.errors.lawyer && (
<FormMessage>
{formState.errors.lawyer.message as any}
</FormMessage>
)}
</FormItem>
{/* 2. Files Uploader */}
<FormItem>
<FormLabel>
Upload Attachments (as a single or multiple files)
</FormLabel>
<input
type="file"
multiple
onChange={handleFileChange}
className="block text-sm mt-1"
accept="application/pdf,image/*"
/>
<FormDescription className="text-[12px]">
Upload any documents, images, or supporting materials. (Files
are NOT uploaded to any server.)
</FormDescription>
{uploadedFiles.length > 0 && (
<ul className="text-xs text-muted-foreground mt-1">
{uploadedFiles.map((file) => (
<li key={file.name}>{file.name}</li>
))}
</ul>
)}
</FormItem>
{/* 3. Aggrieved Parties */}
<fieldset className="border rounded px-3 py-2">
<legend className="text-sm font-bold mb-2 px-1">
Aggrieved Parties{" "}
<span className="font-normal text-muted-foreground">
(Applicant[s])
</span>
</legend>
{aggrievedFields.map((item, idx) => (
<div key={item.id} className="flex gap-2 mb-2">
<input
type="text"
placeholder="Full Name"
{...register(`aggrieved.${idx}.name`, {
required: true,
})}
className="flex-1 px-2 py-1 rounded border"
/>
<input
type="text"
placeholder="Address"
{...register(`aggrieved.${idx}.address`, {
required: true,
})}
className="flex-1 px-2 py-1 rounded border"
/>
<Button
type="button"
variant="ghost"
size="icon"
onClick={() => removeAggrieved(idx)}
disabled={aggrievedFields.length === 1}
>
×
</Button>
</div>
))}
<Button
type="button"
size="sm"
variant="secondary"
onClick={() => appendAggrieved({ name: "", address: "" })}
className="mt-1"
>
+ Add Party
</Button>
</fieldset>
{/* 4. Respondent Agencies */}
<fieldset className="border rounded px-3 py-2">
<legend className="text-sm font-bold mb-2 px-1">
Govt. Agencies/Depts (Respondents)
</legend>
{govFields.map((item, idx) => (
<div key={item.id} className="flex gap-2 mb-2">
<input
type="text"
placeholder="Agency Name"
{...register(`government.${idx}.name`, {
required: true,
})}
className="flex-1 px-2 py-1 rounded border"
/>
<input
type="text"
placeholder="Address"
{...register(`government.${idx}.address`, {
required: true,
})}
className="flex-1 px-2 py-1 rounded border"
/>
<Button
type="button"
variant="ghost"
size="icon"
onClick={() => removeGovernment(idx)}
disabled={govFields.length === 1}
>
×
</Button>
</div>
))}
<Button
type="button"
size="sm"
variant="secondary"
onClick={() => appendGovernment({ name: "", address: "" })}
className="mt-1"
>
+ Add Agency
</Button>
</fieldset>
{/* 5. Facts */}
<FormItem>
<FormLabel>
Facts Leading to Violation of Fundamental Rights
</FormLabel>
<textarea
{...register("facts", { required: true })}
rows={3}
placeholder="Describe the situation, incidents, background..."
className="w-full border rounded px-3 py-2"
/>
<FormMessage />
</FormItem>
{/* 6. Dates */}
<FormItem>
<FormLabel>Relevant Dates (of Grievance)</FormLabel>
<input
type="text"
placeholder="e.g. Feb 2023 - May 2024"
{...register("dates", { required: true })}
className="w-full border rounded px-3 py-2"
/>
<FormMessage />
</FormItem>
{/* 7. Prayers/Relief */}
<FormItem>
<FormLabel>Prayers / Relief Sought</FormLabel>
<textarea
{...register("prayers", { required: true })}
rows={2}
placeholder="State what you want the court to grant."
className="w-full border rounded px-3 py-2"
/>
<FormMessage />
</FormItem>
{/* 8. Extra/precedent */}
<FormItem>
<FormLabel>Precedent Cases (if any)</FormLabel>
<input
type="text"
placeholder="E.g. Vishaka v. State of Rajasthan, AIR 1997 SC 3011"
{...register("precedence")}
className="w-full border rounded px-3 py-2"
/>
</FormItem>
<FormItem>
<FormLabel>Additional Comments</FormLabel>
<textarea
{...register("comments")}
rows={2}
placeholder="Any other relevant comment"
className="w-full border rounded px-3 py-2"
/>
</FormItem>
<div className="flex items-center justify-between mt-4 gap-2">
<Button
type="button"
variant="ghost"
onClick={() => {
reset();
setOutput(null);
setUploadedFiles([]);
}}
>
Reset Form
</Button>
<div className="flex gap-2">
<Button
type="button"
size="lg"
onClick={onRenderPdf}
disabled={!output}
variant="secondary"
>
Render as PDF
</Button>
<Button type="submit" size="lg">
Generate & Download PIL Markdown
</Button>
</div>
</div>
</form>
</Form>
{output && (
<div className="mt-8 border bg-muted rounded px-4 py-4 overflow-x-auto text-xs max-h-[320px]">
<div className="font-bold mb-2 text-primary">
Your Draft (preview):
</div>
<pre>{output}</pre>
</div>
)}
</div>
</main>
</div>
);
}

View file

@ -1,3 +1,5 @@
// sdt-project/src/app/page.tsx
import React from "react";
import Link from "next/link";
import Image from "next/image";
@ -24,13 +26,15 @@ export default function Home() {
<a href="#" className="hover:underline">
Contact
</a>
<Link href="/file-pil" className="ml-4">
<Button size="sm" variant="outline">
File PIL
</Button>
</Link>
</nav>
<div className="md:hidden">
{/* Placeholder for mobile menu icon - you can add a hamburger icon here */}
</div>
<div className="md:hidden">{/* Hamburger... */}</div>
</div>
</header>
<main className="flex-grow py-20 px-8">
<div className="container mx-auto text-center">
<h1 className="text-4xl sm:text-5xl md:text-6xl font-bold mb-6">
@ -41,10 +45,12 @@ export default function Home() {
interest litigation with ease and efficiency. Streamline your PIL
process, from drafting to case management.
</p>
<Button size="lg">Learn More</Button>
<Link href="/file-pil">
<Button size="lg">File PIL Now</Button>
</Link>
<div className="mt-12">
<Image
src="/legal-concept.svg" // Placeholder image - replace with a relevant image
src="/legal-concept.svg"
alt="Legal Concept Illustration"
width={800}
height={400}
@ -54,57 +60,10 @@ export default function Home() {
</div>
</div>
</main>
{/* ...rest is as before */}
<section className="py-16 px-8 bg-secondary/10 dark:bg-secondary/20">
<div className="container mx-auto text-center">
<h2 className="text-3xl font-semibold mb-8">Key Features</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<Image
src="/feature-drafting.svg" // Placeholder icon
alt="Drafting Icon"
width={50}
height={50}
className="mx-auto mb-4 dark:invert"
/>
<h3 className="font-semibold mb-2">Guided Drafting</h3>
<p className="text-sm text-muted-foreground">
Step-by-step assistance in preparing your PIL drafts, ensuring
legal compliance.
</p>
</div>
<div>
<Image
src="/feature-management.svg" // Placeholder icon
alt="Management Icon"
width={50}
height={50}
className="mx-auto mb-4 dark:invert"
/>
<h3 className="font-semibold mb-2">Case Management</h3>
<p className="text-sm text-muted-foreground">
Organize and manage all your PIL cases efficiently, tracking
deadlines and progress.
</p>
</div>
<div>
<Image
src="/feature-collaboration.svg" // Placeholder icon
alt="Collaboration Icon"
width={50}
height={50}
className="mx-auto mb-4 dark:invert"
/>
<h3 className="font-semibold mb-2">Collaboration Tools</h3>
<p className="text-sm text-muted-foreground">
Facilitate teamwork with secure document sharing and
communication features.
</p>
</div>
</div>
</div>
{/* ... */}
</section>
<footer className="py-8 px-8 border-t text-center text-sm text-muted-foreground">
<div className="container mx-auto">
&copy; {new Date().getFullYear()} PIL-legal. All rights reserved.