From 3a88b2469072d1611bc5844224fdb4b5d87574ac Mon Sep 17 00:00:00 2001 From: Krish Agarwal Date: Tue, 13 Oct 2026 15:24:48 +0530 Subject: [PATCH] terms and policy --- README.md | 3 +- public/assets/upi-qr.svg | 2 +- src/app/privacy/page.tsx | 98 +++++++++++++++++ src/app/sitemap.ts | 4 +- src/app/terms/page.tsx | 103 ++++++++++++++++++ src/components/events/EventsChrome.tsx | 4 +- src/components/innovision/Innovision.tsx | 8 +- src/components/innovision/SiteFooter.tsx | 14 +-- src/components/legal/Legal.module.css | 16 +++ src/components/legal/LegalPage.tsx | 36 ++++++ src/config/payment.ts | 8 +- src/lib/security.ts | 2 +- supabase/manual/allow_iter_soa.sql | 2 +- supabase/manual/remove_free_internal_tier.sql | 4 +- supabase/schema.sql | 4 +- 15 files changed, 281 insertions(+), 27 deletions(-) create mode 100644 src/app/privacy/page.tsx create mode 100644 src/app/terms/page.tsx create mode 100644 src/components/legal/Legal.module.css create mode 100644 src/components/legal/LegalPage.tsx diff --git a/README.md b/README.md index 4a59339..279d6e0 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,8 @@ The registration APIs (`/api/register`, `/api/upload`) check the same switch on Edit [`src/config/payment.ts`](src/config/payment.ts). The fee must match `REGISTRATION_FEE_INR` in [`src/lib/security.ts`](src/lib/security.ts), which is what the server records. Then regenerate -`public/assets/upi-qr.svg` from the new `UPI_PAY_LINK` with any QR encoder, and scan it to check before deploying. +`public/assets/upi-qr.svg` from the new `UPI_PAY_LINK` as a single byte-mode segment (see the comment in +`payment.ts`), and scan it to check before deploying. ### Add gallery photos diff --git a/public/assets/upi-qr.svg b/public/assets/upi-qr.svg index 5b37fdd..adab88a 100644 --- a/public/assets/upi-qr.svg +++ b/public/assets/upi-qr.svg @@ -1 +1 @@ - + diff --git a/src/app/privacy/page.tsx b/src/app/privacy/page.tsx new file mode 100644 index 0000000..f4d7501 --- /dev/null +++ b/src/app/privacy/page.tsx @@ -0,0 +1,98 @@ +import Link from 'next/link'; +import LegalPage, { LegalContacts } from '@/components/legal/LegalPage'; +import { pageMetadata } from '@/lib/seo'; + +export const metadata = pageMetadata({ + title: 'Privacy Policy', + description: 'How INNOVISION 2026, the techno-management festival of NIT Rourkela, collects, uses and protects your personal data.', + path: '/privacy', +}); + +/** + * /privacy. Describes what the site actually does with personal data; keep it in step with the code when the data + * collected changes (registration form fields, supabase/schema.sql, the analytics in src/app/layout.tsx). + */ +export default function PrivacyPage() { + return ( + +

+ This policy explains what personal data the INNOVISION 2026 website collects, why, who can see it and what you can + do about it. “We” means the INNOVISION 2026 organising team at the National Institute of Technology + Rourkela, Odisha. By signing in or registering you agree to this policy and to our{' '} + Terms and Conditions. +

+ +

What we collect

+ + +

Why we use it

+ +

We do not sell your data, use it for advertising or send you marketing email.

+ +

Who can see it

+ +

We share data with anyone else only if the law requires it.

+ +

Cookies and browser storage

+

+ We use two sign-in cookies, which last up to 7 and 30 days, so you stay logged in. The site also keeps small, + temporary notes in your browser's session storage, for example to reopen the registration form after you sign + in. We use no advertising or tracking cookies. +

+ +

How long we keep it

+

+ We keep registration data, payment screenshots and check-in records only for as long as we need them to run + INNOVISION 2026, handle questions about payments or entry and settle the fest's accounts. After that we delete them. +

+ +

How we protect it

+

+ Data is sent over encrypted connections. Access is limited by role: participants can read only their own records, + and only the registration team can see payment screenshots. Entry-pass codes are stored encrypted. No system is + perfectly secure, but we take reasonable steps to protect your data. +

+ +

Your choices and rights

+ +

+ Deleting your data cancels your registration and entry pass. We may keep a record of a payment where that is needed + to settle accounts or resolve a dispute. +

+ +

Changes to this policy

+

+ If we change this policy we will update it on this page and change the date at the top. Significant changes will + also be announced on the site. +

+ +

Contact us

+

For any privacy question or request, contact the organising team:

+ +
+ ); +} diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 3c571f8..72537d1 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -10,7 +10,7 @@ import { WORLDS } from '@/components/innovision/data'; * whose #/ hash routes on the home page search engines treat as the home page itself; the gallery and schedule views * have no pages of their own. /register and /merch are listed only while they render their public teaser pages; once * their launch switch (src/config/launch.ts) is on, they redirect instead (to sign-in, or to the #/merch store view) - * and are left out. Staff pages (/admin) and the API never appear. + * and are left out. /privacy and /terms are always listed. Staff pages (/admin) and the API never appear. * * No lastModified: nothing in the project records when a page's content last changed, and a build date is not that. */ @@ -21,6 +21,8 @@ export default function sitemap(): MetadataRoute.Sitemap { ...WORLDS.map((w) => `/events/${w.slug}`), ...(REGISTRATIONS_OPEN ? [] : ['/register']), ...(MERCH_STORE_OPEN ? [] : ['/merch']), + '/privacy', + '/terms', ]; return paths.map((path) => ({ url: `${SITE_URL}${path}` })); } diff --git a/src/app/terms/page.tsx b/src/app/terms/page.tsx new file mode 100644 index 0000000..15d5da3 --- /dev/null +++ b/src/app/terms/page.tsx @@ -0,0 +1,103 @@ +import Link from 'next/link'; +import LegalPage, { LegalContacts } from '@/components/legal/LegalPage'; +import { REGISTRATION_FEE } from '@/config/payment'; +import { pageMetadata } from '@/lib/seo'; + +export const metadata = pageMetadata({ + title: 'Terms and Conditions', + description: 'The terms for registering for and attending INNOVISION 2026, the techno-management festival of NIT Rourkela.', + path: '/terms', +}); + +/** /terms. The registration and entry rules here mirror the registration flow and the QR check-in at the gate. */ +export default function TermsPage() { + return ( + +

+ These terms apply to everyone who uses the INNOVISION 2026 website, registers for the fest or attends it. + “We” means the INNOVISION 2026 organising team at the National Institute of Technology Rourkela, Odisha. + By signing in or registering you accept these terms and our Privacy Policy. +

+ +

Accounts and registration

+ + +

Fee and payment

+ + +

Refunds

+

+ The registration fee is non-refundable once your registration is confirmed. If you were charged twice, or your + payment reached us but your registration was rejected, contact us with your UTR and we will look into a refund. + If the fest is cancelled, we will announce how fees will be refunded. +

+ +

Entry pass

+ + +

At the fest

+ + +

Changes to the fest

+

+ Schedules, venues, line-ups, prizes and event formats may change. We will post changes on the site. If the fest + has to be postponed or cancelled, we will announce what happens to registrations. +

+ +

Using this website

+ + +

Liability

+

+ We run the site and the fest with reasonable care, but we provide the site “as is” and can't promise it + will always be available or error-free. As far as the law allows, our liability for any registration is limited to + the fee you paid for it. +

+ +

Changes to these terms

+

+ We may update these terms. The date at the top shows the latest version. Continuing to use the site after a change + means you accept the updated terms. +

+ +

Contact us

+

For questions about registration, payments or these terms, contact the organising team:

+ +
+ ); +} diff --git a/src/components/events/EventsChrome.tsx b/src/components/events/EventsChrome.tsx index c5b26cb..e4bcc89 100644 --- a/src/components/events/EventsChrome.tsx +++ b/src/components/events/EventsChrome.tsx @@ -6,7 +6,7 @@ import { Logo } from '@/components/innovision/icons'; import styles from './EventsPage.module.css'; /** - * Frame shared by /events and /events/: the INNOVISION wordmark home link, the breadcrumb trail the page's + * Frame shared by /events, /events/, /privacy and /terms: the INNOVISION wordmark home link, the breadcrumb trail the page's * BreadcrumbList JSON-LD describes, and a footer linking every world page. Server-rendered, no client JS. * Links into the animated explorer (/#/...) are plain , not : the explorer reads its hash route once its * loader finishes, and a full page load is what keeps that hash (as for a visitor arriving from search). @@ -49,6 +49,8 @@ export default function EventsChrome({ trail, children }: { trail: [string, stri
  • Explore the worlds
  • Registrations
  • Official merch
  • +
  • Privacy Policy
  • +
  • Terms and Conditions
  • © 2026 Innovision · NIT Rourkela, Odisha

    diff --git a/src/components/innovision/Innovision.tsx b/src/components/innovision/Innovision.tsx index 9b84f07..9581055 100644 --- a/src/components/innovision/Innovision.tsx +++ b/src/components/innovision/Innovision.tsx @@ -5,7 +5,7 @@ import { CLICKABLE, preloadClick, unlockClick, playClick } from './clickSound'; /* eslint-disable @typescript-eslint/no-explicit-any -- view-model is dynamically constructed and consumed across many child views */ /* eslint-disable @typescript-eslint/no-unused-vars -- some destructured vars are kept for future use */ -import { Component, createRef, memo, type ComponentType, type FormEvent, type MouseEvent, type TouchEvent, type WheelEvent } from 'react'; +import { Component, createRef, memo, type ComponentType, type MouseEvent, type TouchEvent, type WheelEvent } from 'react'; import dynamic from 'next/dynamic'; import { useRouter } from 'next/navigation'; import gsap from 'gsap'; @@ -2639,12 +2639,6 @@ export class Innovision extends Component { bagVis: (s.bagOpen ? 'visible' : 'hidden') as 'visible' | 'hidden', bagDelay: s.bagOpen ? '0s' : '.8s', bagO: s.bagOpen ? 1 : 0, bagX: s.bagOpen ? '0%' : '100%', bagHidden: !s.bagOpen, openBag: () => { this.openLazy('bag', { bagOpen: true }); }, closeBag: () => this.setState({ bagOpen: false }), - subscribe: (e: FormEvent) => { - e.preventDefault(); - const f = e.currentTarget, email = f.elements.namedItem('email') as HTMLInputElement | null; - if (!email || !email.value) return; - f.reset(); this.toast("You're on the mission list."); - }, toastMsg: s.toastMsg, heroChars: 'INNOVISION'.split('').map((ch) => ({ ch })), briefWords: BRIEF.split(' '), diff --git a/src/components/innovision/SiteFooter.tsx b/src/components/innovision/SiteFooter.tsx index 75df9ce..19f8d71 100644 --- a/src/components/innovision/SiteFooter.tsx +++ b/src/components/innovision/SiteFooter.tsx @@ -12,7 +12,7 @@ export function LiveFooter() { return v && ; } -/** Rounded starfield footer with newsletter sign-up. */ +/** Rounded starfield footer. */ export default function SiteFooter({ v }: { v: V }) { return (