Merge pull request 'new-public-booking' (#14) from new-public-booking into development
Reviewed-on: https://gitea.2pidev.com/jselesan/playzer/pulls/14
This commit is contained in:
1206
apps/frontend/src/components/ui/stepper.tsx
Normal file
1206
apps/frontend/src/components/ui/stepper.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
|||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
type UserAvatarProps = {
|
type UserAvatarProps = {
|
||||||
src?: string | null;
|
src?: string | null;
|
||||||
@@ -22,25 +21,9 @@ export function UserAvatar({
|
|||||||
size = 'default',
|
size = 'default',
|
||||||
className,
|
className,
|
||||||
}: UserAvatarProps) {
|
}: UserAvatarProps) {
|
||||||
const [imageError, setImageError] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setImageError(false);
|
|
||||||
}, [src]);
|
|
||||||
|
|
||||||
const canShowImage = Boolean(src) && !imageError;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Avatar size={size} className={className}>
|
<Avatar size={size} className={className}>
|
||||||
{canShowImage && (
|
<AvatarImage src={src ?? undefined} alt={alt} />
|
||||||
<AvatarImage
|
|
||||||
src={src ?? undefined}
|
|
||||||
alt={alt}
|
|
||||||
onError={() => {
|
|
||||||
setImageError(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<AvatarFallback>{getInitials(fallbackText)}</AvatarFallback>
|
<AvatarFallback>{getInitials(fallbackText)}</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
);
|
);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -244,4 +244,46 @@ body,
|
|||||||
border: 3px solid transparent;
|
border: 3px solid transparent;
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.public-booking-light {
|
||||||
|
background: #eaf2f4;
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-booking-light .public-booking-frame {
|
||||||
|
background: radial-gradient(circle at 18% 10%, rgba(16, 185, 129, 0.18), transparent 28%),
|
||||||
|
radial-gradient(circle at 82% 18%, rgba(59, 130, 246, 0.14), transparent 30%),
|
||||||
|
linear-gradient(180deg, #f8fbfc 0%, #edf5f7 52%, #e5eef2 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-booking-light .public-booking-panel {
|
||||||
|
background: rgba(255, 255, 255, 0.78);
|
||||||
|
border-color: rgba(15, 23, 42, 0.13);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.72), 0 18px 48px rgba(15, 23, 42, 0.09);
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-booking-light [class*="border-white"] {
|
||||||
|
border-color: rgba(15, 23, 42, 0.13);
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-booking-light [class*="bg-white"] {
|
||||||
|
background-color: rgba(15, 23, 42, 0.045);
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-booking-light [class*="text-white"] {
|
||||||
|
color: rgba(15, 23, 42, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-booking-light .text-emerald-400,
|
||||||
|
.public-booking-light .text-cyan-300 {
|
||||||
|
color: #059669;
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-booking-light .bg-emerald-500 {
|
||||||
|
background-color: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-booking-light .text-red-300 {
|
||||||
|
color: #dc2626;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
61
apps/frontend/src/lib/compose-refs.ts
Normal file
61
apps/frontend/src/lib/compose-refs.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
type PossibleRef<T> = React.Ref<T> | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a given ref to a given value
|
||||||
|
* This utility takes care of different types of refs: callback refs and RefObject(s)
|
||||||
|
*/
|
||||||
|
function setRef<T>(ref: PossibleRef<T>, value: T) {
|
||||||
|
if (typeof ref === 'function') {
|
||||||
|
return ref(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref !== null && ref !== undefined) {
|
||||||
|
ref.current = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility to compose multiple refs together
|
||||||
|
* Accepts callback refs and RefObject(s)
|
||||||
|
*/
|
||||||
|
function composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {
|
||||||
|
return (node) => {
|
||||||
|
let hasCleanup = false;
|
||||||
|
const cleanups = refs.map((ref) => {
|
||||||
|
const cleanup = setRef(ref, node);
|
||||||
|
if (!hasCleanup && typeof cleanup === 'function') {
|
||||||
|
hasCleanup = true;
|
||||||
|
}
|
||||||
|
return cleanup;
|
||||||
|
});
|
||||||
|
|
||||||
|
// React <19 will log an error to the console if a callback ref returns a
|
||||||
|
// value. We don't use ref cleanups internally so this will only happen if a
|
||||||
|
// user's ref callback returns a value, which we only expect if they are
|
||||||
|
// using the cleanup functionality added in React 19.
|
||||||
|
if (hasCleanup) {
|
||||||
|
return () => {
|
||||||
|
for (let i = 0; i < cleanups.length; i++) {
|
||||||
|
const cleanup = cleanups[i];
|
||||||
|
if (typeof cleanup === 'function') {
|
||||||
|
cleanup();
|
||||||
|
} else {
|
||||||
|
setRef(refs[i], null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom hook that composes multiple refs
|
||||||
|
* Accepts callback refs and RefObject(s)
|
||||||
|
*/
|
||||||
|
function useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {
|
||||||
|
return React.useCallback(composeRefs(...refs), refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { composeRefs, useComposedRefs };
|
||||||
@@ -3,7 +3,7 @@ import { NotFoundPage } from '@/features/not-found/not-found-page';
|
|||||||
import { ServerErrorPage } from '@/features/server-error/server-error-page';
|
import { ServerErrorPage } from '@/features/server-error/server-error-page';
|
||||||
import type { ApiClient } from '@/lib/api-client';
|
import type { ApiClient } from '@/lib/api-client';
|
||||||
import type { AuthContextValue } from '@/lib/auth';
|
import type { AuthContextValue } from '@/lib/auth';
|
||||||
import { Outlet, createRootRouteWithContext } from '@tanstack/react-router';
|
import { Outlet, createRootRouteWithContext, useLocation } from '@tanstack/react-router';
|
||||||
|
|
||||||
type RouterContext = {
|
type RouterContext = {
|
||||||
auth: AuthContextValue;
|
auth: AuthContextValue;
|
||||||
@@ -17,6 +17,13 @@ export const Route = createRootRouteWithContext<RouterContext>()({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function RootRoute() {
|
function RootRoute() {
|
||||||
|
const location = useLocation();
|
||||||
|
const isPublicBookingRoute = /^\/[^/]+\/booking(?:\/|$)/.test(location.pathname);
|
||||||
|
|
||||||
|
if (isPublicBookingRoute) {
|
||||||
|
return <Outlet />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
|
|||||||
Reference in New Issue
Block a user