Compare commits

..

1 Commits

Author SHA1 Message Date
96cc08b61e fix(deps): update nextjs monorepo to v16
Some checks failed
renovate/stability-days Updates have met minimum release age requirement
Check / Lint and Check (pull_request) Failing after 17s
Check / Lint and Check (push) Failing after 16s
2025-11-15 03:01:07 +00:00
15 changed files with 483 additions and 479 deletions

6
.eslintrc.json Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": [
"next/core-web-vitals",
"next/typescript"
]
}

View File

@@ -13,7 +13,7 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4
@@ -28,4 +28,4 @@ jobs:
run: pnpm install run: pnpm install
- name: Run check - name: Run check
run: pnpm run lint run: pnpm run check

View File

@@ -41,7 +41,7 @@ export default function SignUp() {
// Double-check signup isn't blocked before submitting // Double-check signup isn't blocked before submitting
const currentStatus = isSignupBlocked(); const currentStatus = isSignupBlocked();
if (currentStatus.blocked) { if (currentStatus.blocked) {
setResponse(currentStatus.message ?? "Sign-ups are currently closed."); setResponse(currentStatus.message || "Sign-ups are currently closed.");
return; return;
} }
setSubmitted(true); setSubmitted(true);
@@ -50,7 +50,6 @@ export default function SignUp() {
function SignupForm() { function SignupForm() {
return ( return (
<Form {...form}> <Form {...form}>
{/* eslint-disable-next-line @typescript-eslint/no-misused-promises */}
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField <FormField
control={form.control} control={form.control}
@@ -91,10 +90,8 @@ export default function SignUp() {
<FormControl> <FormControl>
<Button <Button
variant={"outline"} variant={"outline"}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition className={cn("w-[240px] pl-3 text-left font-normal", !field.value && "text-muted-foreground")}
className={cn("w-[240px] pl-3 text-left font-normal", field.value && "text-muted-foreground")}
> >
{/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */}
{field.value ? format(field.value, "PPP") : <span>Pick a date</span>} {field.value ? format(field.value, "PPP") : <span>Pick a date</span>}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" /> <CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button> </Button>

View File

@@ -3,19 +3,26 @@
import * as React from "react"; import * as React from "react";
import * as LabelPrimitive from "@radix-ui/react-label"; import * as LabelPrimitive from "@radix-ui/react-label";
import { Slot } from "@radix-ui/react-slot"; import { Slot } from "@radix-ui/react-slot";
import { Controller, ControllerProps, FieldPath, FieldValues, FormProvider, useFormContext } from "react-hook-form"; import {
Controller,
ControllerProps,
FieldPath,
FieldValues,
FormProvider,
useFormContext,
} from "react-hook-form";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
const Form = FormProvider; const Form = FormProvider;
interface FormFieldContextValue< type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues, TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues> TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> { > = {
name: TName; name: TName;
} };
const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue); const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);
@@ -39,7 +46,7 @@ const useFormField = () => {
const fieldState = getFieldState(fieldContext.name, formState); const fieldState = getFieldState(fieldContext.name, formState);
if (!fieldContext.name) { if (!fieldContext) {
throw new Error("useFormField should be used within <FormField>"); throw new Error("useFormField should be used within <FormField>");
} }
@@ -55,9 +62,9 @@ const useFormField = () => {
}; };
}; };
interface FormItemContextValue { type FormItemContextValue = {
id: string; id: string;
} };
const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue); const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);
@@ -75,57 +82,88 @@ const FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivEl
FormItem.displayName = "FormItem"; FormItem.displayName = "FormItem";
const FormLabel = React.forwardRef< const FormLabel = React.forwardRef<
React.ComponentRef<typeof LabelPrimitive.Root>, React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...props }, ref) => { >(({ className, ...props }, ref) => {
const { error, formItemId } = useFormField(); const { error, formItemId } = useFormField();
return <Label ref={ref} className={cn(error && "text-destructive", className)} htmlFor={formItemId} {...props} />; return (
<Label
ref={ref}
className={cn(error && "text-destructive", className)}
htmlFor={formItemId}
{...props}
/>
);
}); });
FormLabel.displayName = "FormLabel"; FormLabel.displayName = "FormLabel";
const FormControl = React.forwardRef<React.ComponentRef<typeof Slot>, React.ComponentPropsWithoutRef<typeof Slot>>( const FormControl = React.forwardRef<
({ ...props }, ref) => { React.ElementRef<typeof Slot>,
const { error, formItemId, formDescriptionId, formMessageId } = useFormField(); React.ComponentPropsWithoutRef<typeof Slot>
>(({ ...props }, ref) => {
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
return ( return (
<Slot <Slot
ref={ref} ref={ref}
id={formItemId} id={formItemId}
aria-describedby={!error ? formDescriptionId : `${formDescriptionId} ${formMessageId}`} aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}
aria-invalid={!!error} aria-invalid={!!error}
{...props} {...props}
/> />
); );
} });
);
FormControl.displayName = "FormControl"; FormControl.displayName = "FormControl";
const FormDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>( const FormDescription = React.forwardRef<
({ className, ...props }, ref) => { HTMLParagraphElement,
const { formDescriptionId } = useFormField(); React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => {
const { formDescriptionId } = useFormField();
return <p ref={ref} id={formDescriptionId} className={cn("text-sm text-muted-foreground", className)} {...props} />; return (
} <p
); ref={ref}
id={formDescriptionId}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
);
});
FormDescription.displayName = "FormDescription"; FormDescription.displayName = "FormDescription";
const FormMessage = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>( const FormMessage = React.forwardRef<
({ className, children, ...props }, ref) => { HTMLParagraphElement,
const { error, formMessageId } = useFormField(); React.HTMLAttributes<HTMLParagraphElement>
const body = error ? String(error.message) : children; >(({ className, children, ...props }, ref) => {
const { error, formMessageId } = useFormField();
const body = error ? String(error?.message) : children;
if (!body) { if (!body) {
return null; return null;
}
return (
<p ref={ref} id={formMessageId} className={cn("text-sm font-medium text-destructive", className)} {...props}>
{body}
</p>
);
} }
);
return (
<p
ref={ref}
id={formMessageId}
className={cn("text-sm font-medium text-destructive", className)}
{...props}
>
{body}
</p>
);
});
FormMessage.displayName = "FormMessage"; FormMessage.displayName = "FormMessage";
export { useFormField, Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormField }; export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
};

View File

@@ -11,7 +11,7 @@ const labelVariants = cva(
); );
const Label = React.forwardRef< const Label = React.forwardRef<
React.ComponentRef<typeof LabelPrimitive.Root>, React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants> React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} /> <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />

View File

@@ -10,7 +10,7 @@ const Popover = PopoverPrimitive.Root;
const PopoverTrigger = PopoverPrimitive.Trigger; const PopoverTrigger = PopoverPrimitive.Trigger;
const PopoverContent = React.forwardRef< const PopoverContent = React.forwardRef<
React.ComponentRef<typeof PopoverPrimitive.Content>, React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal> <PopoverPrimitive.Portal>

View File

@@ -13,7 +13,7 @@ const SelectGroup = SelectPrimitive.Group;
const SelectValue = SelectPrimitive.Value; const SelectValue = SelectPrimitive.Value;
const SelectTrigger = React.forwardRef< const SelectTrigger = React.forwardRef<
React.ComponentRef<typeof SelectPrimitive.Trigger>, React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger <SelectPrimitive.Trigger
@@ -33,7 +33,7 @@ const SelectTrigger = React.forwardRef<
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
const SelectScrollUpButton = React.forwardRef< const SelectScrollUpButton = React.forwardRef<
React.ComponentRef<typeof SelectPrimitive.ScrollUpButton>, React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton> React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton <SelectPrimitive.ScrollUpButton
@@ -47,7 +47,7 @@ const SelectScrollUpButton = React.forwardRef<
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
const SelectScrollDownButton = React.forwardRef< const SelectScrollDownButton = React.forwardRef<
React.ComponentRef<typeof SelectPrimitive.ScrollDownButton>, React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton> React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton <SelectPrimitive.ScrollDownButton
@@ -61,7 +61,7 @@ const SelectScrollDownButton = React.forwardRef<
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName; SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
const SelectContent = React.forwardRef< const SelectContent = React.forwardRef<
React.ComponentRef<typeof SelectPrimitive.Content>, React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => ( >(({ className, children, position = "popper", ...props }, ref) => (
<SelectPrimitive.Portal> <SelectPrimitive.Portal>
@@ -93,7 +93,7 @@ const SelectContent = React.forwardRef<
SelectContent.displayName = SelectPrimitive.Content.displayName; SelectContent.displayName = SelectPrimitive.Content.displayName;
const SelectLabel = React.forwardRef< const SelectLabel = React.forwardRef<
React.ComponentRef<typeof SelectPrimitive.Label>, React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.Label <SelectPrimitive.Label
@@ -105,7 +105,7 @@ const SelectLabel = React.forwardRef<
SelectLabel.displayName = SelectPrimitive.Label.displayName; SelectLabel.displayName = SelectPrimitive.Label.displayName;
const SelectItem = React.forwardRef< const SelectItem = React.forwardRef<
React.ComponentRef<typeof SelectPrimitive.Item>, React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => ( >(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item <SelectPrimitive.Item
@@ -128,7 +128,7 @@ const SelectItem = React.forwardRef<
SelectItem.displayName = SelectPrimitive.Item.displayName; SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef< const SelectSeparator = React.forwardRef<
React.ComponentRef<typeof SelectPrimitive.Separator>, React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SelectPrimitive.Separator <SelectPrimitive.Separator

View File

@@ -1,37 +0,0 @@
// @ts-check
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
import tseslint from "typescript-eslint";
const eslintConfig = defineConfig([
// Next.js core-web-vitals and TypeScript configs
...nextVitals,
...nextTs,
// Add strict TypeScript rules on top
...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked,
// Configure TypeScript parser options
{
files: ["**/*.{ts,tsx}"],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
// Override default ignores of eslint-config-next
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
// Additional ignores:
"*.mjs",
"tailwind.config.ts",
]),
]);
export default eslintConfig;

View File

@@ -1,12 +1,12 @@
import "server-only"; import "server-only";
export interface listmonkData { export type listmonkData = {
email: string; email: string;
name: string; name: string;
status: "enabled" | "blocklisted"; status: "enabled" | "blocklisted";
lists: number[]; lists: number[];
attribs: Record<string, string>; attribs: Record<string, string>;
} };
async function listmonk(data: listmonkData): Promise<string> { async function listmonk(data: listmonkData): Promise<string> {
const listmonkUrl = process.env.LISTMONK_URL ?? "http://localhost:9000/api/"; const listmonkUrl = process.env.LISTMONK_URL ?? "http://localhost:9000/api/";

View File

@@ -5,7 +5,7 @@ function testScenario(description: string, date: Date, expected: boolean) {
const result = isSignupBlocked(date); const result = isSignupBlocked(date);
const status = result.blocked === expected ? "✅ PASS" : "❌ FAIL"; const status = result.blocked === expected ? "✅ PASS" : "❌ FAIL";
console.log(`${status} ${description}`); console.log(`${status} ${description}`);
console.log(` Expected blocked: ${String(expected)}, Got: ${String(result.blocked)}`); console.log(` Expected blocked: ${expected}, Got: ${result.blocked}`);
if (result.message) { if (result.message) {
console.log(` Message: ${result.message}`); console.log(` Message: ${result.message}`);
} }

View File

@@ -1,7 +1,7 @@
import eventConfig from "@/event-dates.json"; import eventConfig from "@/event-dates.json";
export function isSignupBlocked(currentTime?: Date): { blocked: boolean; message?: string } { export function isSignupBlocked(currentTime?: Date): { blocked: boolean; message?: string } {
const now = currentTime ?? new Date(); const now = currentTime || new Date();
const cutoffTime = eventConfig.cutoffTime || "15:00"; const cutoffTime = eventConfig.cutoffTime || "15:00";
const blockDurationHours = eventConfig.blockDurationHours || 6; const blockDurationHours = eventConfig.blockDurationHours || 6;

View File

@@ -6,7 +6,7 @@
"dev": "next dev --turbopack", "dev": "next dev --turbopack",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next typegen && eslint . && npx tsc --noEmit" "check": "next lint && npx tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@hookform/resolvers": "^5.1.1", "@hookform/resolvers": "^5.1.1",
@@ -18,14 +18,14 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cssnano": "^7.1.0", "cssnano": "^7.1.0",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"lucide-react": "^0.554.0", "lucide-react": "^0.553.0",
"next": "16.0.3", "next": "^16.0.0",
"next-plausible": "^3.12.4", "next-plausible": "^3.12.4",
"postcss-flexbugs-fixes": "^5.0.2", "postcss-flexbugs-fixes": "^5.0.2",
"postcss-preset-env": "^10.2.4", "postcss-preset-env": "^10.2.4",
"react": "19.2.0", "react": "^19.1.0",
"react-day-picker": "^9.8.0", "react-day-picker": "^9.8.0",
"react-dom": "19.2.0", "react-dom": "^19.1.0",
"react-hook-form": "^7.60.0", "react-hook-form": "^7.60.0",
"tailwind-merge": "^3.3.1", "tailwind-merge": "^3.3.1",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
@@ -34,22 +34,15 @@
"devDependencies": { "devDependencies": {
"@tailwindcss/postcss": "4.1.17", "@tailwindcss/postcss": "4.1.17",
"@types/node": "24.10.1", "@types/node": "24.10.1",
"@types/react": "19.2.6", "@types/react": "19.2.3",
"@types/react-dom": "19.2.3", "@types/react-dom": "19.2.2",
"eslint": "9.39.1", "eslint": "9.39.1",
"eslint-config-next": "16.0.3", "eslint-config-next": "16.0.1",
"eslint-config-prettier": "10.1.8", "eslint-config-prettier": "10.1.8",
"postcss": "8.5.6", "postcss": "8.5.6",
"tailwindcss": "4.1.17", "tailwindcss": "4.1.17",
"turbo": "2.6.1", "turbo": "2.6.0",
"typescript": "5.9.3", "typescript": "5.9.3"
"typescript-eslint": "^8.47.0"
}, },
"packageManager": "pnpm@10.23.0", "packageManager": "pnpm@10.20.0"
"pnpm": {
"overrides": {
"@types/react": "19.2.6",
"@types/react-dom": "19.2.3"
}
}
} }

695
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,27 @@
const config = { const config = {
plugins: { plugins: {
'@tailwindcss/postcss': {}, '@tailwindcss/postcss': {},
"postcss-flexbugs-fixes": {
"postcss-preset-env": {
autoprefixer: {
flexbox: "no-2009",
},
stage: 3,
features: {
"custom-properties": false,
},
},
"@fullhuman/postcss-purgecss": {
content: [
"./pages/**/*.{js,jsx,ts,tsx}",
"./components/**/*.{js,jsx,ts,tsx}",
],
defaultExtractor: (content) => content.match(/[\w-/:]+(?<!:)/g) || [],
safelist: ["html", "body"],
},
},
cssnano: {}, cssnano: {},
}, },
}; };

View File

@@ -10,7 +10,7 @@
"moduleResolution": "bundler", "moduleResolution": "bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "react-jsx", "jsx": "preserve",
"incremental": true, "incremental": true,
"plugins": [ "plugins": [
{ {
@@ -22,13 +22,6 @@
}, },
"target": "ES2023" "target": "ES2023"
}, },
"include": [ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "event-dates.json"],
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"event-dates.json",
".next/dev/types/**/*.ts"
],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }