Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
2 changes: 2 additions & 0 deletions messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@
"searchPlaceholder": "Suchen",
"searchError": "Etwas ist schiefgelaufen. Erneut versuchen?",
"searchNoResults": "Keine Ergebnisse. Tippe weiter oder verfeinere deine Suche",
"returnToListing": "Zurück zum Eintrag",
"loadingPins": "Wird geladen…",
"didYouKnow": "Wusstest du schon?",
"steps": {
"find": {
Expand Down
2 changes: 2 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@
"searchPlaceholder": "Search",
"searchError": "Something went wrong. Try again?",
"searchNoResults": "No results. Keep typing or refine your search",
"returnToListing": "Return to listing",
"loadingPins": "Loading…",
"didYouKnow": "Did you know?",
"steps": {
"find": {
Expand Down
2 changes: 2 additions & 0 deletions messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@
"searchPlaceholder": "Buscar",
"searchError": "Algo salió mal. ¿Intentarlo de nuevo?",
"searchNoResults": "Sin resultados. Sigue escribiendo o ajusta tu búsqueda",
"returnToListing": "Volver al anuncio",
"loadingPins": "Cargando…",
"didYouKnow": "¿Sabías que?",
"steps": {
"find": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { cache } from "react";
import type { Metadata } from "next/types";

import { createClient } from "@/utils/supabase/server";
import { siteConfig } from "@/config/site";
import { generateListingMetadata } from "@/utils/listingUtils";
import MapPageClient from "@/components/MapPageClient";
import { cache } from "react";
import MapPageClient from "@/features/map";
import type { Listing } from "@/types/listing";

type MapPageSearchParams = {
listing?: string;
};

type MapPageProps = {
searchParams: Promise<MapPageSearchParams>;
};

// Fetch data only once and use across metadata and page
const getInitialData = cache(async (listingSlug) => {
const getInitialData = cache(async (listingSlug: string | undefined) => {
const supabase = await createClient();

// Get user first
const {
data: { user },
} = await supabase.auth.getUser();

// Then get listing data if slug exists
const listingResponse = listingSlug
? await supabase
.from(user ? "listings_private_data" : "listings_public_data")
Expand All @@ -24,11 +32,13 @@ const getInitialData = cache(async (listingSlug) => {

return {
user,
listing: listingResponse?.data,
listing: (listingResponse?.data ?? null) as Listing | null,
};
});

export async function generateMetadata({ searchParams }) {
export async function generateMetadata({
searchParams,
}: MapPageProps): Promise<Metadata> {
const listingSlug = (await searchParams)?.listing;

if (!listingSlug) {
Expand All @@ -42,18 +52,17 @@ export async function generateMetadata({ searchParams }) {

const { user, listing } = await getInitialData(listingSlug);

// Use shared utility to generate metadata
return generateListingMetadata(listing, user);
}

export default async function Page({ searchParams }) {
export default async function Page({ searchParams }: MapPageProps) {
const listingSlug = (await searchParams)?.listing;
const { user, listing } = await getInitialData(listingSlug);

return (
<MapPageClient
user={user}
initialListingSlug={listingSlug}
initialListingSlug={listingSlug ?? null}
initialListing={listing}
/>
);
Expand Down
1 change: 0 additions & 1 deletion src/app/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,6 @@ export async function fetchListingsInView(
return [];
}

console.log(`Successfully fetched ${data?.length || 0} listings`);
return data || [];
} catch (error) {
console.error("Fatal error in fetchListingsInView:", {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
"use client";
import type { ReactNode } from "react";
import type { User } from "@supabase/supabase-js";
import { useDeviceContext } from "@/hooks/useDeviceContext";
import { Drawer } from "vaul";
import Button from "@/components/Button";
import ChatWindow from "@/components/ChatWindow";
import ListingCta from "@/components/ListingCta";
import { styled } from "@pigment-css/react";

import type { Listing } from "@/types/listing";

const sidebarWidth = "clamp(20rem, 30vw, 30rem)";

const StyledDrawerOverlay = styled(Drawer.Overlay)({
Expand All @@ -15,7 +19,7 @@ const StyledDrawerOverlay = styled(Drawer.Overlay)({
});

const ListingCtaContainer = styled("div")({
padding: "0 1rem", // Match padding from other parts of ListingRead
padding: "0 1rem",

"& > *": {
width: "100%",
Expand All @@ -24,17 +28,16 @@ const ListingCtaContainer = styled("div")({

const StyledDrawerContent = styled(Drawer.Content)(({ theme }) => ({
background: theme.colors.background.top,
borderRadius: `${theme.corners.base} ${theme.corners.base} 0 0`, // Match over drawer content
borderRadius: `${theme.corners.base} ${theme.corners.base} 0 0`,

overflowX: "hidden",

"&::after": {
display: "none", // Otherwise seems to include side scroll, even when overflowX hidden
display: "none",
},

marginTop: "24px",
// maxHeight: "95%",
height: "95%", // Take up full height even if the message contents aren't overflowing yet
height: "95%",
position: "fixed",
bottom: "0",
left: "0",
Expand All @@ -43,7 +46,7 @@ const StyledDrawerContent = styled(Drawer.Content)(({ theme }) => ({
flexDirection: "column",

"@media (min-width: 768px)": {
borderRadius: theme.corners.base, // Match over drawer content
borderRadius: theme.corners.base,
height: "unset",
marginTop: "unset",
top: "24px",
Expand All @@ -52,54 +55,55 @@ const StyledDrawerContent = styled(Drawer.Content)(({ theme }) => ({
left: "unset",
outline: "none",
width: sidebarWidth,
// height: "100%",
},
}));

// We need to define two different drawer components, because depending on the 'modal' prop, a different number of hooks will be rendered
// React doesn't like when we conditionally change the number of hooks. It's better to just render a separate component for each case
// Shared drawer props to reduce repetition
const getDrawerProps = ({
isNested,
isChatDrawerOpen,
setIsChatDrawerOpen,
isDesktop,
...rest
}) => ({
isNested,
direction: isDesktop ? "right" : undefined,
open: isChatDrawerOpen,
onOpenChange: setIsChatDrawerOpen,
...rest,
});

const ModalDrawer = (props) => {
const DrawerComponent = props.isNested ? Drawer.NestedRoot : Drawer.Root;
return <DrawerComponent modal={true} {...getDrawerProps(props)} />;
type ListingChatDrawerProps = {
isNested?: boolean;
user: User | null;
listing: Listing;
isChatDrawerOpen: boolean;
setIsChatDrawerOpen: (open: boolean) => void;
existingThread: unknown;
listingDisplayName: string;
};

const NonModalDrawer = (props) => {
const DrawerComponent = props.isNested ? Drawer.NestedRoot : Drawer.Root;
return <DrawerComponent modal={false} {...getDrawerProps(props)} />;
type SharedDrawerProps = {
isNested?: boolean;
open: boolean;
onOpenChange: (open: boolean) => void;
direction?: "right";
children?: ReactNode;
};

// We need two drawer variants because `modal` changes which hooks vaul renders.
function ModalDrawer({ isNested, ...rest }: SharedDrawerProps) {
const DrawerComponent = isNested ? Drawer.NestedRoot : Drawer.Root;
return <DrawerComponent modal={true} {...rest} />;
}

function NonModalDrawer({ isNested, ...rest }: SharedDrawerProps) {
const DrawerComponent = isNested ? Drawer.NestedRoot : Drawer.Root;
return <DrawerComponent modal={false} {...rest} />;
}

export default function ListingChatDrawer({
isNested,
user,
listing,
isChatDrawerOpen,
setIsChatDrawerOpen,
existingThread,
listingDisplayName,
...props
}) {
listingDisplayName: _listingDisplayName,
}: ListingChatDrawerProps) {
const { isDesktop, hasTouch } = useDeviceContext();

// We can infer modal behavior based on presentation
// If it's a mobile breakpoint, always use a model
// If it's a desktop breakpoint, only use a modal if it's NOT a nested drawer
// Mobile: always modal. Desktop: modal only if NOT a nested drawer.
const shouldUseModal = !isDesktop || isNested === false;

const visibility = listing.visibility ?? undefined;
const isStub = listing.is_stub ?? undefined;

const drawerContent = (
<>
<ListingCtaContainer>
Expand All @@ -108,14 +112,14 @@ export default function ListingChatDrawer({
<ListingCta
viewer="owner"
slug={listing.slug}
visibility={listing.visibility}
isStub={listing.is_stub}
visibility={visibility}
isStub={isStub}
/>
) : listing.is_stub ? (
<ListingCta
viewer="guest"
slug={listing.slug}
visibility={listing.visibility}
visibility={visibility}
isStub={true}
/>
) : (
Expand All @@ -129,8 +133,8 @@ export default function ListingChatDrawer({
<ListingCta
viewer="guest"
slug={listing.slug}
visibility={listing.visibility}
isStub={listing.is_stub}
visibility={visibility}
isStub={isStub}
/>
)}
</ListingCtaContainer>
Expand All @@ -154,10 +158,9 @@ export default function ListingChatDrawer({
return (
<DrawerComponent
isNested={isNested}
isChatDrawerOpen={isChatDrawerOpen}
setIsChatDrawerOpen={setIsChatDrawerOpen}
isDesktop={isDesktop}
{...props}
open={isChatDrawerOpen}
onOpenChange={setIsChatDrawerOpen}
direction={isDesktop ? "right" : undefined}
>
{drawerContent}
</DrawerComponent>
Expand Down
Loading
Loading