Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
**/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
Expand All @@ -10,7 +10,7 @@
/coverage

# next.js
/.next/
**/.next/
/out/

# production
Expand All @@ -34,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# turbo
**/.turbo
File renamed without changes.
File renamed without changes.
File renamed without changes.
48 changes: 48 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "vaas-web",
"version": "0.1.1",
"private": true,
"scripts": {
"dev": "next dev --turbo",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@hookform/resolvers": "^3.4.2",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-tooltip": "^1.0.7",
"@tabler/icons-react": "^3.5.0",
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.11",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"date-fns": "^3.6.0",
"framer-motion": "^11.2.10",
"mini-svg-data-uri": "^1.4.4",
"next": "^15.0.0-rc.0",
"react": "^19.0.0-rc-6d3110b4d9-20240531",
"react-day-picker": "^8.10.1",
"react-dom": "^19.0.0-rc-6d3110b4d9-20240531",
"react-hook-form": "^7.51.5",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/react-dom": "^18.3.0",
"babel-plugin-react-compiler": "^0.0.0-experimental-938cd9a-20240601",
"eslint-config-next": "^15.0.0-rc.0",
"postcss": "^8",
"tailwindcss": "^3.4.1"
},
"trustedDependencies": ["@vercel/speed-insights", "sharp"]
}
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"use client"
"use client";

import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react";
import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "@/lib/utils"
import { cn } from "@/lib/utils";

const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);

const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
Expand All @@ -20,7 +20,7 @@ const Label = React.forwardRef<
className={cn(labelVariants(), className)}
{...props}
/>
))
Label.displayName = LabelPrimitive.Root.displayName
));
Label.displayName = LabelPrimitive.Root.displayName;

export { Label }
export { Label };
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"use client"
"use client";

import {
Toast,
Expand All @@ -7,11 +7,11 @@ import {
ToastProvider,
ToastTitle,
ToastViewport,
} from "@/components/ui/toast"
import { useToast } from "@/components/ui/use-toast"
} from "@/components/ui/toast";
import { useToast } from "@/components/ui/use-toast";

export function Toaster() {
const { toasts } = useToast()
const { toasts } = useToast();

return (
<ToastProvider>
Expand All @@ -27,9 +27,9 @@ export function Toaster() {
{action}
<ToastClose />
</Toast>
)
);
})}
<ToastViewport />
</ToastProvider>
)
);
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,106 +1,103 @@
"use client"
"use client";

// Inspired by react-hot-toast library
import * as React from "react"
import * as React from "react";

import type {
ToastActionElement,
ToastProps,
} from "@/components/ui/toast"
import type { ToastActionElement, ToastProps } from "@/components/ui/toast";

const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000
const TOAST_LIMIT = 1;
const TOAST_REMOVE_DELAY = 1000000;

type ToasterToast = ToastProps & {
id: string
title?: React.ReactNode
description?: React.ReactNode
action?: ToastActionElement
}
id: string;
title?: React.ReactNode;
description?: React.ReactNode;
action?: ToastActionElement;
};

const actionTypes = {
ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST",
} as const
} as const;

let count = 0
let count = 0;

function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER
return count.toString()
count = (count + 1) % Number.MAX_SAFE_INTEGER;
return count.toString();
}

type ActionType = typeof actionTypes
type ActionType = typeof actionTypes;

type Action =
| {
type: ActionType["ADD_TOAST"]
toast: ToasterToast
type: ActionType["ADD_TOAST"];
toast: ToasterToast;
}
| {
type: ActionType["UPDATE_TOAST"]
toast: Partial<ToasterToast>
type: ActionType["UPDATE_TOAST"];
toast: Partial<ToasterToast>;
}
| {
type: ActionType["DISMISS_TOAST"]
toastId?: ToasterToast["id"]
type: ActionType["DISMISS_TOAST"];
toastId?: ToasterToast["id"];
}
| {
type: ActionType["REMOVE_TOAST"]
toastId?: ToasterToast["id"]
}
type: ActionType["REMOVE_TOAST"];
toastId?: ToasterToast["id"];
};

interface State {
toasts: ToasterToast[]
toasts: ToasterToast[];
}

const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();

const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
return
return;
}

const timeout = setTimeout(() => {
toastTimeouts.delete(toastId)
toastTimeouts.delete(toastId);
dispatch({
type: "REMOVE_TOAST",
toastId: toastId,
})
}, TOAST_REMOVE_DELAY)
});
}, TOAST_REMOVE_DELAY);

toastTimeouts.set(toastId, timeout)
}
toastTimeouts.set(toastId, timeout);
};

export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "ADD_TOAST":
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
}
};

case "UPDATE_TOAST":
return {
...state,
toasts: state.toasts.map((t) =>
t.id === action.toast.id ? { ...t, ...action.toast } : t
t.id === action.toast.id ? { ...t, ...action.toast } : t,
),
}
};

case "DISMISS_TOAST": {
const { toastId } = action
const { toastId } = action;

// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId)
addToRemoveQueue(toastId);
} else {
state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id)
})
addToRemoveQueue(toast.id);
});
}

return {
Expand All @@ -111,46 +108,46 @@ export const reducer = (state: State, action: Action): State => {
...t,
open: false,
}
: t
: t,
),
}
};
}
case "REMOVE_TOAST":
if (action.toastId === undefined) {
return {
...state,
toasts: [],
}
};
}
return {
...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId),
}
};
}
}
};

const listeners: Array<(state: State) => void> = []
const listeners: Array<(state: State) => void> = [];

let memoryState: State = { toasts: [] }
let memoryState: State = { toasts: [] };

function dispatch(action: Action) {
memoryState = reducer(memoryState, action)
memoryState = reducer(memoryState, action);
listeners.forEach((listener) => {
listener(memoryState)
})
listener(memoryState);
});
}

type Toast = Omit<ToasterToast, "id">
type Toast = Omit<ToasterToast, "id">;

function toast({ ...props }: Toast) {
const id = genId()
const id = genId();

const update = (props: ToasterToast) =>
dispatch({
type: "UPDATE_TOAST",
toast: { ...props, id },
})
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
});
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });

dispatch({
type: "ADD_TOAST",
Expand All @@ -159,36 +156,36 @@ function toast({ ...props }: Toast) {
id,
open: true,
onOpenChange: (open) => {
if (!open) dismiss()
if (!open) dismiss();
},
},
})
});

return {
id: id,
dismiss,
update,
}
};
}

function useToast() {
const [state, setState] = React.useState<State>(memoryState)
const [state, setState] = React.useState<State>(memoryState);

React.useEffect(() => {
listeners.push(setState)
listeners.push(setState);
return () => {
const index = listeners.indexOf(setState)
const index = listeners.indexOf(setState);
if (index > -1) {
listeners.splice(index, 1)
listeners.splice(index, 1);
}
}
}, [state])
};
}, [state]);

return {
...state,
toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
}
};
}

export { useToast, toast }
export { useToast, toast };
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading