diff --git a/app/components/ScrollRevealWrapper.tsx b/app/components/ScrollRevealWrapper.tsx
index a258086..214891c 100644
--- a/app/components/ScrollRevealWrapper.tsx
+++ b/app/components/ScrollRevealWrapper.tsx
@@ -14,31 +14,36 @@ export default function ScrollRevealWrapper({ children, instant = false }: Scrol
useEffect(() => {
if (instant) return;
+ const current = domRef.current;
+ if (!current) return;
+
const observer = new IntersectionObserver(
([entry]) => {
- setIsVisible(entry.isIntersecting);
+ if (entry.isIntersecting) {
+ setIsVisible(true);
+ observer.unobserve(entry.target);
+ }
},
{
- threshold: 0.05,
- rootMargin: "-6% 0px -6% 0px",
+ threshold: 0.02,
+ rootMargin: "0px 0px -50px 0px",
}
);
- const current = domRef.current;
- if (current) observer.observe(current);
+ observer.observe(current);
return () => {
- if (current) observer.unobserve(current);
+ observer.disconnect();
};
}, [instant]);
return (
{children}
diff --git a/app/globals.css b/app/globals.css
index 8dd5450..02dcbfb 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1255,6 +1255,7 @@ main>div {
animation-delay: 0.5s;
opacity: 0;
}
+
/* ─── Signed-in avatar in the navbar ────────────────────────────────
* Replaces the Login pill once a session is restored, matching what the
* previous navbar did. Sized to the pill's height so swapping between the
@@ -1316,9 +1317,15 @@ main>div {
* Applies only below the tablet breakpoint, so the compact desktop styling of
* the admin forms is untouched. */
@media (max-width: 768px) {
+
input,
select,
textarea {
font-size: 16px;
}
}
+
+input[type="checkbox"],
+input[type="radio"] {
+ accent-color: #ff5500;
+}
\ No newline at end of file
diff --git a/next.config.ts b/next.config.ts
index 93e3438..204cccd 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -54,6 +54,19 @@ const nextConfig: NextConfig = {
];
},
+ async redirects() {
+ return [
+ // Permanent redirect for printed QR code that points to the old event.
+ // The QR is already in circulation so we redirect server-side (308) so
+ // every scanner, browser and search engine follows it automatically.
+ {
+ source: "/Events/6a74c22b4a467d7a0aac0cc6",
+ destination: "/Events/6a7797c26a9a4d018da54ba1",
+ permanent: true,
+ },
+ ];
+ },
+
// Note: legacy capitalised URLs (/Events, /Team, /SignUp …) are *not*
// redirected here. Next matches a redirect `source` case-insensitively, so a
// rule from "/Events" to "/events" also matches "/events" and loops
diff --git a/src/components/Core/Input.jsx b/src/components/Core/Input.jsx
index 25cca67..971a6e4 100644
--- a/src/components/Core/Input.jsx
+++ b/src/components/Core/Input.jsx
@@ -143,7 +143,7 @@ const Input = (props) => {
containerStyle,
style,
placeholder,
- value,
+ value = "",
onChange,
label,
options,
@@ -169,6 +169,8 @@ const Input = (props) => {
return currentDate.getTime() < selectedDate.getTime();
};
+ const safeValue = value ?? "";
+
const getInputTypes = () => {
switch (type) {
case "text":
@@ -179,7 +181,7 @@ const Input = (props) => {
type={type}
style={style || {}}
placeholder={placeholder}
- value={value}
+ value={safeValue}
onChange={onChange}
{...rest}
/>
@@ -193,7 +195,7 @@ const Input = (props) => {
type={type}
style={style || {}}
placeholder={placeholder}
- value={value}
+ value={safeValue}
onChange={onChange}
{...rest}
/>
@@ -207,7 +209,7 @@ const Input = (props) => {
type={type}
style={style || {}}
placeholder={placeholder}
- value={value}
+ value={safeValue}
onChange={onChange}
{...rest}
/>
@@ -281,31 +283,20 @@ const Input = (props) => {
);
case "radio":
return (
-
+
@@ -313,31 +304,20 @@ const Input = (props) => {
);
case "checkbox":
return (
-
+
@@ -360,7 +340,7 @@ const Input = (props) => {
type={showPassword ? "text" : "password"}
style={style || {}}
placeholder={placeholder}
- value={value}
+ value={safeValue}
onChange={onChange}
{...rest}
/>
@@ -515,7 +495,7 @@ const Input = (props) => {
type={type}
style={style || {}}
placeholder={placeholder}
- value={value}
+ value={safeValue}
onChange={onChange}
{...rest}
/>
diff --git a/src/components/Core/styles/Core.module.scss b/src/components/Core/styles/Core.module.scss
index 11cd791..954eb0e 100644
--- a/src/components/Core/styles/Core.module.scss
+++ b/src/components/Core/styles/Core.module.scss
@@ -54,10 +54,89 @@
font-weight: normal;
}
-.containerInput {
+.checkboxWrapper {
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ gap: 12px;
+ margin: 12px 0;
+ cursor: pointer;
+ user-select: none;
+}
+
+.checkboxInput {
+ appearance: none;
+ -webkit-appearance: none;
+ width: 20px !important;
+ height: 20px !important;
+ min-width: 20px !important;
+ min-height: 20px !important;
+ max-width: 20px !important;
+ max-height: 20px !important;
+ border-radius: 6px !important;
+ border: 1.5px solid rgba(255, 255, 255, 0.35) !important;
+ background-color: rgba(255, 255, 255, 0.05) !important;
+ margin: 2px 0 0 0 !important;
+ padding: 0 !important;
+ cursor: pointer;
position: relative;
- width: auto;
+ outline: none;
+ flex-shrink: 0;
+ transition: all 0.2s ease;
+
+ &:hover {
+ border-color: #ff8a00 !important;
+ }
+
+ &:checked {
+ background-color: #ff5500 !important;
+ border-color: #ff5500 !important;
+
+ &::after {
+ content: "";
+ position: absolute;
+ left: 6px;
+ top: 2px;
+ width: 5px;
+ height: 10px;
+ border: solid #ffffff;
+ border-width: 0 2.5px 2.5px 0;
+ transform: rotate(45deg);
+ }
+ }
+
+ &:focus-visible {
+ box-shadow: 0 0 0 2px rgba(255, 138, 0, 0.4);
+ }
+}
+
+:global(input[type="radio"].checkboxInput),
+.checkboxInput[type="radio"] {
+ border-radius: 50% !important;
+
+ &:checked::after {
+ content: "";
+ position: absolute;
+ top: 5px;
+ left: 5px;
+ width: 8px;
+ height: 8px;
+ border: none;
+ border-radius: 50%;
+ background-color: #ffffff;
+ transform: none;
+ }
}
+
+.checkboxLabel {
+ color: #ffffff;
+ font-size: 0.875rem;
+ line-height: 1.45;
+ cursor: pointer;
+ margin: 0;
+ user-select: none;
+}
+
.input {
display: flex;
outline: none;
diff --git a/src/features/Modals/Profile/Admin/PreviewForm.jsx b/src/features/Modals/Profile/Admin/PreviewForm.jsx
index 1781dab..6381a75 100644
--- a/src/features/Modals/Profile/Admin/PreviewForm.jsx
+++ b/src/features/Modals/Profile/Admin/PreviewForm.jsx
@@ -654,7 +654,7 @@ const PreviewForm = ({
₹{eventAmount}
-
+
{safeLink ? (
+