2 Commits

Author SHA1 Message Date
yohlo
6ed77dd471 idk 2025-09-24 07:59:13 -05:00
yohlo
94ea44c66e drawer fixes 2025-09-23 15:04:29 -05:00
15 changed files with 66 additions and 29 deletions

View File

@@ -6,7 +6,7 @@
"scripts": { "scripts": {
"dev": "vite dev --host 0.0.0.0", "dev": "vite dev --host 0.0.0.0",
"build": "vite build && tsc --noEmit", "build": "vite build && tsc --noEmit",
"start": "vite start" "start": "node .output/server/index.mjs"
}, },
"dependencies": { "dependencies": {
"@hello-pangea/dnd": "^18.0.1", "@hello-pangea/dnd": "^18.0.1",
@@ -21,15 +21,15 @@
"@svgmoji/noto": "^3.2.0", "@svgmoji/noto": "^3.2.0",
"@tanstack/react-query": "^5.66.0", "@tanstack/react-query": "^5.66.0",
"@tanstack/react-query-devtools": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0",
"@tanstack/react-router": "^1.130.12", "@tanstack/react-router": "1.130.12",
"@tanstack/react-router-devtools": "^1.130.13", "@tanstack/react-router-devtools": "1.130.13",
"@tanstack/react-router-with-query": "^1.130.12", "@tanstack/react-router-with-query": "1.130.12",
"@tanstack/react-start": "^1.130.15", "@tanstack/react-start": "1.130.15",
"@tanstack/react-virtual": "^3.13.12",
"@tiptap/pm": "^3.4.3", "@tiptap/pm": "^3.4.3",
"@tiptap/react": "^3.4.3", "@tiptap/react": "^3.4.3",
"@tiptap/starter-kit": "^3.4.3", "@tiptap/starter-kit": "^3.4.3",
"@types/ioredis": "^4.28.10", "@types/ioredis": "^4.28.10",
"dotenv": "^17.2.2",
"embla-carousel-react": "^8.6.0", "embla-carousel-react": "^8.6.0",
"framer-motion": "^12.23.12", "framer-motion": "^12.23.12",
"ioredis": "^5.7.0", "ioredis": "^5.7.0",

View File

@@ -5,6 +5,10 @@ import { routeTree } from "./routeTree.gen";
import { DefaultCatchBoundary } from "../components/DefaultCatchBoundary"; import { DefaultCatchBoundary } from "../components/DefaultCatchBoundary";
import { defaultHeaderConfig } from "@/features/core/hooks/use-router-config"; import { defaultHeaderConfig } from "@/features/core/hooks/use-router-config";
import dotenv from 'dotenv';
dotenv.config();
export function createRouter() { export function createRouter() {
const queryClient = new QueryClient({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {

View File

@@ -19,7 +19,6 @@ export const ServerRoute = createServerFileRoute('/api/spotify/token').methods({
) )
} }
// Refresh access token
const tokenResponse = await fetch('https://accounts.spotify.com/api/token', { const tokenResponse = await fetch('https://accounts.spotify.com/api/token', {
method: 'POST', method: 'POST',
headers: { headers: {
@@ -46,7 +45,6 @@ export const ServerRoute = createServerFileRoute('/api/spotify/token').methods({
const tokens = await tokenResponse.json() const tokens = await tokenResponse.json()
// Return new tokens
return new Response( return new Response(
JSON.stringify({ JSON.stringify({
access_token: tokens.access_token, access_token: tokens.access_token,

View File

@@ -72,7 +72,8 @@ export const ServerRoute = createServerFileRoute('/api/teams/upload-logo')
}); });
} }
if (!team.players.map(p => p.id).includes(context.userId) && !isAdmin) const user = await pbAdmin.getPlayerByAuthId(context.userAuthId)
if (!team.players.map(p => p.id).includes(user!.id) && !isAdmin)
return new Response('Unauthorized', { status: 403 }); return new Response('Unauthorized', { status: 403 });
logger.info('Uploading team logo', { logger.info('Uploading team logo', {

View File

@@ -1,8 +1,7 @@
import { Box, Container, Flex, Loader, useComputedColorScheme } from "@mantine/core"; import { Box, Container, Flex, Loader, useComputedColorScheme } from "@mantine/core";
import { PropsWithChildren, Suspense, useEffect } from "react"; import { PropsWithChildren, Suspense, useEffect, useRef } from "react";
import { Drawer as VaulDrawer } from "vaul"; import { Drawer as VaulDrawer } from "vaul";
import styles from "./styles.module.css"; import styles from "./styles.module.css";
import FullScreenLoader from "../full-screen-loader";
interface DrawerProps extends PropsWithChildren { interface DrawerProps extends PropsWithChildren {
title?: string; title?: string;
@@ -17,6 +16,7 @@ const Drawer: React.FC<DrawerProps> = ({
onChange, onChange,
}) => { }) => {
const colorScheme = useComputedColorScheme("light"); const colorScheme = useComputedColorScheme("light");
const contentRef = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
const appElement = document.querySelector(".app") as HTMLElement; const appElement = document.querySelector(".app") as HTMLElement;
@@ -59,11 +59,31 @@ const Drawer: React.FC<DrawerProps> = ({
}; };
}, [opened, colorScheme]); }, [opened, colorScheme]);
useEffect(() => {
if (!opened || !contentRef.current) return;
const resizeObserver = new ResizeObserver(() => {
if (contentRef.current) {
const drawerContent = contentRef.current.closest('[data-vaul-drawer-wrapper]');
if (drawerContent) {
(drawerContent as HTMLElement).style.height = 'auto';
(drawerContent as HTMLElement).offsetHeight;
}
}
});
resizeObserver.observe(contentRef.current);
return () => {
resizeObserver.disconnect();
};
}, [opened, children]);
return ( return (
<VaulDrawer.Root open={opened} onOpenChange={onChange}> <VaulDrawer.Root open={opened} onOpenChange={onChange}>
<VaulDrawer.Portal> <VaulDrawer.Portal>
<VaulDrawer.Overlay className={styles.drawerOverlay} /> <VaulDrawer.Overlay className={styles.drawerOverlay} />
<VaulDrawer.Content className={styles.drawerContent} aria-describedby="drawer"> <VaulDrawer.Content className={styles.drawerContent} aria-describedby="drawer" ref={contentRef}>
<Container flex={1} p="md"> <Container flex={1} p="md">
<Box <Box
mb="sm" mb="sm"
@@ -74,7 +94,7 @@ const Drawer: React.FC<DrawerProps> = ({
mr="auto" mr="auto"
style={{ borderRadius: "9999px" }} style={{ borderRadius: "9999px" }}
/> />
<Container mah="fit-content" mx="auto" maw="28rem" px={0}> <Container mx="auto" maw="28rem" px={0}>
<VaulDrawer.Title>{title}</VaulDrawer.Title> <VaulDrawer.Title>{title}</VaulDrawer.Title>
<Suspense fallback={ <Suspense fallback={
<Flex justify='center' align='center' w='100%' h={400}> <Flex justify='center' align='center' w='100%' h={400}>

View File

@@ -2,7 +2,7 @@ import { PropsWithChildren, useCallback } from "react";
import { useIsMobile } from "@/hooks/use-is-mobile"; import { useIsMobile } from "@/hooks/use-is-mobile";
import Drawer from "./drawer"; import Drawer from "./drawer";
import Modal from "./modal"; import Modal from "./modal";
import { Box, ScrollArea } from "@mantine/core"; import { ScrollArea } from "@mantine/core";
interface SheetProps extends PropsWithChildren { interface SheetProps extends PropsWithChildren {
title?: string; title?: string;
@@ -29,7 +29,7 @@ const Sheet: React.FC<SheetProps> = ({ title, children, opened, onChange }) => {
scrollbars="y" scrollbars="y"
type="scroll" type="scroll"
> >
<Box mah="70vh">{children}</Box> {children}
</ScrollArea> </ScrollArea>
</SheetComponent> </SheetComponent>
); );

View File

@@ -11,10 +11,13 @@
border-top-left-radius: 20px; border-top-left-radius: 20px;
border-top-right-radius: 20px; border-top-right-radius: 20px;
margin-top: 24px; margin-top: 24px;
height: fit-content; height: auto !important;
min-height: fit-content;
max-height: 100dvh;
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
outline: none; outline: none;
transition: height 0.2s ease-out;
} }

View File

@@ -107,7 +107,7 @@ function SwipeableTabs({
const activeSlideRef = slideRefs.current[activeTab]; const activeSlideRef = slideRefs.current[activeTab];
if (!activeSlideRef) return; if (!activeSlideRef) return;
let timeoutId: number; let timeoutId: any;
const resizeObserver = new ResizeObserver(() => { const resizeObserver = new ResizeObserver(() => {
clearTimeout(timeoutId); clearTimeout(timeoutId);
timeoutId = setTimeout(updateHeight, 16); timeoutId = setTimeout(updateHeight, 16);

View File

@@ -438,7 +438,6 @@ export const SpotifyProvider: React.FC<PropsWithChildren> = ({ children }) => {
activeDevice, activeDevice,
isLoading, isLoading,
error, error,
// Capture/Resume state
capturedState, capturedState,
isCaptureLoading, isCaptureLoading,
isResumeLoading, isResumeLoading,
@@ -453,11 +452,9 @@ export const SpotifyProvider: React.FC<PropsWithChildren> = ({ children }) => {
getDevices, getDevices,
setActiveDevice, setActiveDevice,
refreshPlaybackState, refreshPlaybackState,
// Capture/Resume methods
capturePlaybackState, capturePlaybackState,
resumePlaybackState, resumePlaybackState,
clearCapturedState, clearCapturedState,
// Search
searchTracks, searchTracks,
}; };

View File

@@ -60,6 +60,7 @@ export const useMe = () => {
const errorData = error?.response?.data; const errorData = error?.response?.data;
if (errorData?.error === "SESSION_REFRESH_REQUIRED") { if (errorData?.error === "SESSION_REFRESH_REQUIRED") {
const currentUrl = window.location.pathname + window.location.search; const currentUrl = window.location.pathname + window.location.search;
console.log('redirecting 3')
window.location.href = `/refresh-session?redirect=${encodeURIComponent(currentUrl)}`; window.location.href = `/refresh-session?redirect=${encodeURIComponent(currentUrl)}`;
return false; return false;
} }

View File

@@ -10,6 +10,11 @@ class PocketBaseAdminClient {
public authPromise: Promise<void>; public authPromise: Promise<void>;
constructor() { constructor() {
console.log('Environment variables loaded:', {
POCKETBASE_URL: process.env.POCKETBASE_URL,
POCKETBASE_ADMIN_EMAIL: process.env.POCKETBASE_ADMIN_EMAIL,
POCKETBASE_ADMIN_PASSWORD: process.env.POCKETBASE_ADMIN_PASSWORD,
});
this.pb = new PocketBase(process.env.POCKETBASE_URL); this.pb = new PocketBase(process.env.POCKETBASE_URL);
this.pb.beforeSend = (url, options) => { this.pb.beforeSend = (url, options) => {

View File

@@ -23,15 +23,15 @@ export function useOptimisticMutation<TData, TVariables = unknown>(
return { previousData }; return { previousData };
}, },
onError: (error, variables, context) => { onError: (error, variables, onMutateResult, context) => {
if (context && typeof context === 'object' && 'previousData' in context && context.previousData) { if (context && typeof context === 'object' && 'previousData' in context && context.previousData) {
queryClient.setQueryData(queryKey, context.previousData); queryClient.setQueryData(queryKey, context.previousData);
} }
mutationOptions.onError?.(error, variables, context); mutationOptions.onError?.(error, variables, onMutateResult, context);
}, },
onSettled: (data, error, variables, context) => { onSettled: (data, error, variables, onMutateResult, context) => {
queryClient.invalidateQueries({ queryKey }); queryClient.invalidateQueries({ queryKey });
mutationOptions.onSettled?.(data, error, variables, context); mutationOptions.onSettled?.(data, error, variables, onMutateResult, context);
} }
}); });
} }

View File

@@ -44,6 +44,7 @@ export function useServerMutation<TData, TVariables = unknown>(
if (errorData?.error === "SESSION_REFRESH_REQUIRED") { if (errorData?.error === "SESSION_REFRESH_REQUIRED") {
const currentUrl = window.location.pathname + window.location.search; const currentUrl = window.location.pathname + window.location.search;
window.location.href = `/refresh-session?redirect=${encodeURIComponent(currentUrl)}`; window.location.href = `/refresh-session?redirect=${encodeURIComponent(currentUrl)}`;
console.log('redirecting 2')
throw new Error("SESSION_REFRESH_REQUIRED"); throw new Error("SESSION_REFRESH_REQUIRED");
} }
} catch (parseError) {} } catch (parseError) {}
@@ -52,14 +53,14 @@ export function useServerMutation<TData, TVariables = unknown>(
throw error; throw error;
} }
}, },
onSuccess: (data, variables, context) => { onSuccess: (data, variables, onMutateResult, context) => {
if (showSuccessToast && successMessage) { if (showSuccessToast && successMessage) {
toast.success(successMessage); toast.success(successMessage);
} }
onSuccess?.(data, variables, context); onSuccess?.(data, variables, onMutateResult, context);
}, },
onError: (error, variables, context) => { onError: (error, variables, onMutateResult, context) => {
onError?.(error, variables, context); onError?.(error, variables, onMutateResult, context);
} }
}); });
} }

View File

@@ -79,6 +79,7 @@ export const getSessionContext = async (request: Request, options?: { isServerFu
const url = new URL(request.url); const url = new URL(request.url);
const from = encodeURIComponent(url.pathname + url.search); const from = encodeURIComponent(url.pathname + url.search);
console.log('redirecting')
throw redirect({ throw redirect({
to: "/refresh-session", to: "/refresh-session",
search: { redirect: from } search: { redirect: from }

View File

@@ -18,5 +18,11 @@ export default defineConfig({
}, },
}), }),
react() react()
] ],
build: {
target: 'esnext',
},
ssr: {
target: 'node',
}
}) })