Skip to content

Commit

Permalink
add asset search + throttle
Browse files Browse the repository at this point in the history
  • Loading branch information
Kluskey committed Oct 4, 2024
1 parent faba9c4 commit d1ff26e
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 74 deletions.
146 changes: 79 additions & 67 deletions mirror-2/app/space/[spaceId]/build/(controlBar)/assets.tsx
Original file line number Diff line number Diff line change
@@ -1,84 +1,96 @@
'use client';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { XIcon } from 'lucide-react';
import { z } from "zod";
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Form, FormField, FormItem, FormControl, FormMessage } from '@/components/ui/form';
import { useLazySearchAssetsQuery } from '@/state/supabase';
import { useThrottleCallback } from '@react-hook/throttle'

const imagesData = [
// Mock data for images and text (30 items for 10 rows and 3 columns)
{ src: 'https://via.placeholder.com/150', text: 'Image 1' },
{ src: 'https://via.placeholder.com/150', text: 'Image 2' },
{ src: 'https://via.placeholder.com/150', text: 'Image 3' },
{ src: 'https://via.placeholder.com/150', text: 'Image 4' },
{ src: 'https://via.placeholder.com/150', text: 'Image 5' },
{ src: 'https://via.placeholder.com/150', text: 'Image 6' },
{ src: 'https://via.placeholder.com/150', text: 'Image 7' },
{ src: 'https://via.placeholder.com/150', text: 'Image 8' },
{ src: 'https://via.placeholder.com/150', text: 'Image 9' },
{ src: 'https://via.placeholder.com/150', text: 'Image 10' },
{ src: 'https://via.placeholder.com/150', text: 'Image 11' },
{ src: 'https://via.placeholder.com/150', text: 'Image 12' },
{ src: 'https://via.placeholder.com/150', text: 'Image 13' },
{ src: 'https://via.placeholder.com/150', text: 'Image 14' },
{ src: 'https://via.placeholder.com/150', text: 'Image 15' },
{ src: 'https://via.placeholder.com/150', text: 'Image 16' },
{ src: 'https://via.placeholder.com/150', text: 'Image 17' },
{ src: 'https://via.placeholder.com/150', text: 'Image 18' },
{ src: 'https://via.placeholder.com/150', text: 'Image 19' },
{ src: 'https://via.placeholder.com/150', text: 'Image 20' },
{ src: 'https://via.placeholder.com/150', text: 'Image 21' },
{ src: 'https://via.placeholder.com/150', text: 'Image 22' },
{ src: 'https://via.placeholder.com/150', text: 'Image 23' },
{ src: 'https://via.placeholder.com/150', text: 'Image 24' },
{ src: 'https://via.placeholder.com/150', text: 'Image 25' },
{ src: 'https://via.placeholder.com/150', text: 'Image 26' },
{ src: 'https://via.placeholder.com/150', text: 'Image 27' },
{ src: 'https://via.placeholder.com/150', text: 'Image 28' },
{ src: 'https://via.placeholder.com/150', text: 'Image 29' },
{ src: 'https://via.placeholder.com/150', text: 'Image 30' },
{ src: 'https://via.placeholder.com/150', text: 'Image 11' },
{ src: 'https://via.placeholder.com/150', text: 'Image 12' },
{ src: 'https://via.placeholder.com/150', text: 'Image 13' },
{ src: 'https://via.placeholder.com/150', text: 'Image 14' },
{ src: 'https://via.placeholder.com/150', text: 'Image 15' },
{ src: 'https://via.placeholder.com/150', text: 'Image 16' },
{ src: 'https://via.placeholder.com/150', text: 'Image 17' },
{ src: 'https://via.placeholder.com/150', text: 'Image 18' },
{ src: 'https://via.placeholder.com/150', text: 'Image 19' },
{ src: 'https://via.placeholder.com/150', text: 'Image 20' },
{ src: 'https://via.placeholder.com/150', text: 'Image 21' },
{ src: 'https://via.placeholder.com/150', text: 'Image 22' },
{ src: 'https://via.placeholder.com/150', text: 'Image 23' },
{ src: 'https://via.placeholder.com/150', text: 'Image 24' },
{ src: 'https://via.placeholder.com/150', text: 'Image 25' },
{ src: 'https://via.placeholder.com/150', text: 'Image 26' },
{ src: 'https://via.placeholder.com/150', text: 'Image 27' },
{ src: 'https://via.placeholder.com/150', text: 'Image 28' },
{ src: 'https://via.placeholder.com/150', text: 'Image 29' },
{ src: 'https://via.placeholder.com/150', text: 'Image 30' }

];
const formSchema = z.object({
text: z.string().min(3)
})

export default function Assets() {
const [searchTerm, setSearchTerm] = useState('');
// define the form
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
mode: "onChange",
defaultValues: {
text: "",
},
// errors: error TODO add error handling here
})
const [triggerSearch, { data: assets, isLoading, isSuccess, error }] = useLazySearchAssetsQuery()

const filteredImages = imagesData.filter((image) =>
image.text.toLowerCase().includes(searchTerm.toLowerCase())
);
const throttledSubmit = useThrottleCallback(() => {
triggerSearch({ text: form.getValues("text") })
}, 3, true) // the 4 if 4 FPS
// 2. Define a submit handler.
async function onSubmit(values: z.infer<typeof formSchema>) {
throttledSubmit()
}

// Reset the form values when the space data is fetched
useEffect(() => {
if (assets && isSuccess) {
form.reset({
text: "", // Set the form value once space.name is available
});
}
}, [isSuccess, form]); // Only run this effect when space or isLoading changes

return (
<div className="flex flex-col h-screen">
{/* Search bar */}
<Input
type="text"
placeholder="Search"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="mb-4 w-full"
/>
{/* <NoSsr> */}
<Form {...form} >
<form onSubmit={form.handleSubmit(onSubmit)} className="w-full" onChange={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="text"
render={({ field }) => (
<FormItem>
<FormControl>

<div className="relative">
<Input
type="text"
placeholder="Search"
className="mb-4 w-full"
{...field}
/>
<Button
type="button"
variant="ghost"
size="icon"
className="absolute right-1 top-1/4 -translate-y-1/4 h-7 w-7 text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100"
onClick={() => {
form.reset()
}}
>
<XIcon className="h-4 w-4" />
<span className="sr-only">Clear</span>
</Button>
</div>
</FormControl>
{/* TODO add better styling for this so it doesn't shift the input field */}
<FormMessage />
</FormItem>
)}
/>
</form>
</Form >
{/* </NoSsr> */}


{/* Scrollable area that takes up remaining space */}
<div className="flex-1 overflow-auto">
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 p-4 pb-16">
{filteredImages.map((image, index) => (
{assets?.map((image, index) => (
<div key={index} className="text-center ">
<img
src={image.src}
Expand Down
4 changes: 2 additions & 2 deletions mirror-2/app/space/[spaceId]/build/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ export default async function Layout({ children, params }: {
<div className="absolute pt-16 w-32 h-full">
<Sidebar />
</div>
<div className="absolute left-32 top-16 min-w-96 h-full">
<div className="absolute left-32 top-16 min-w-96 w-96 h-full">
<InnerControlBar />
</div>
<div className="pl-32 pt-16 min-h-screen">
<div className="pl-32 pt-16 min-h-screen h-dvh">
<SpaceViewport />
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions mirror-2/app/space/[spaceId]/build/space-viewport.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export default function SpaceViewport() {
return <main>
return <main className="h-dvh">
<div
className="flex flex-1 items-center justify-center rounded-sm border border-dashed shadow-sm"
className="flex flex-1 items-center justify-center rounded-sm border border-dashed shadow-sm h-dvh"
>
<h3 className="text-2xl font-bold ">
<h3 className="text-2xl font-bold">
3D Viewport
</h3>
</div>
Expand Down
2 changes: 1 addition & 1 deletion mirror-2/hooks/auth.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use client"
import { useAppDispatch, useAppSelector } from "@/hooks/hooks";
import { updateLocalUserState, clearLocalUserState } from "@/state/local";
import { store } from "@/state/store";
import { createSupabaseBrowserClient } from "@/utils/supabase/client";
import { useRouter } from "next/navigation";
import { useEffect } from "react";

export const signOut = async () => {
const supabase = createSupabaseBrowserClient();
Expand Down
1 change: 1 addition & 0 deletions mirror-2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.2",
"@react-hook/throttle": "^2.2.0",
"@reduxjs/toolkit": "^2.2.7",
"@supabase/ssr": "latest",
"@supabase/supabase-js": "latest",
Expand Down
102 changes: 101 additions & 1 deletion mirror-2/state/supabase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export const supabaseApi = createApi({
baseQuery: fakeBaseQuery(),
endpoints: (builder) => ({

/**
* Spaces
*/
createSpace: builder.mutation<any, any>({
queryFn: async () => {
const supabase = createSupabaseBrowserClient();
Expand Down Expand Up @@ -66,10 +69,107 @@ export const supabaseApi = createApi({
}
}),

/**
* Assets
*/
// createAsset: builder.mutation<any, any>({
// queryFn: async () => {
// const supabase = createSupabaseBrowserClient();
// const { data: { user } } = await supabase.auth.getUser()
// if (!user) {
// throw new Error('User not found')
// }
// /**
// * Upload the file
// */


// /**
// * Add to DB
// */
// const { data, error } = await supabase
// .from("assets")
// .insert([{
// name: await generateSpaceName(),
// creator_user_id: user?.id,
// owner_user_id: user.id
// }])
// .select('*')
// .single()

// if (error) {
// return { error: error.message };
// }
// return { data };
// }
// }),

getSingleAsset: builder.query<any, string>({
queryFn: async (assetId) => {
const supabase = createSupabaseBrowserClient();

const { data, error } = await supabase
.from("assets")
.select("*")
.eq("id", assetId)
.single()

if (error) {
return { error: error.message };
}
return { data };
}
}),

searchAssets: builder.query<any, { text: string }>({
queryFn: async ({ text }) => {
const supabase = createSupabaseBrowserClient();

const { data, error } = await supabase
.from("assets")
.select("*")
.eq("name", text)
.single()

if (error) {
return { error: error.message };
}
return { data };
}
}),

updateAsset: builder.mutation<any, { assetId: string, updateData: Record<string, any> }>({
queryFn: async ({ assetId, updateData }) => {
const supabase = createSupabaseBrowserClient();

const { data, error } = await supabase
.from("assets")
.update(updateData)
.eq("id", assetId)
.single()

if (error) {
return { error: error.message };
}
return { data };
}
}),

}),
})

// Export hooks for usage in functional components, which are
// auto-generated based on the defined endpoints
export const { useGetSingleSpaceQuery, useUpdateSpaceMutation, useCreateSpaceMutation } = supabaseApi
export const {
/**
* Spaces
*/
useGetSingleSpaceQuery, useUpdateSpaceMutation, useCreateSpaceMutation,


/**
* Assets
*/
useSearchAssetsQuery, useLazySearchAssetsQuery, useGetSingleAssetQuery, useUpdateAssetMutation
} = supabaseApi

12 changes: 12 additions & 0 deletions mirror-2/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,18 @@
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438"
integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==

"@react-hook/latest@^1.0.2":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@react-hook/latest/-/latest-1.0.3.tgz#c2d1d0b0af8b69ec6e2b3a2412ba0768ac82db80"
integrity sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==

"@react-hook/throttle@^2.2.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@react-hook/throttle/-/throttle-2.2.0.tgz#d0402714a06e1ba0bc1da1fdf5c3c5cd0e08d45a"
integrity sha512-LJ5eg+yMV8lXtqK3lR+OtOZ2WH/EfWvuiEEu0M3bhR7dZRfTyEJKxH1oK9uyBxiXPtWXiQggWbZirMCXam51tg==
dependencies:
"@react-hook/latest" "^1.0.2"

"@reduxjs/toolkit@^2.2.7":
version "2.2.7"
resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.2.7.tgz#199e3d10ccb39267cb5aee92c0262fd9da7fdfb2"
Expand Down

0 comments on commit d1ff26e

Please sign in to comment.