feat: added preview in find

Signed-off-by: Varun Raj <varun@skcript.com>
This commit is contained in:
Varun Raj
2024-12-30 22:02:44 +05:30
parent 9f2f0ef7a6
commit 31e58793be
8 changed files with 98 additions and 70 deletions
-6
View File
@@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
+1
View File
@@ -2,6 +2,7 @@
const config = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
+5 -11
View File
@@ -1,10 +1,10 @@
import React, { useState } from 'react'
import style from './findInputStyle'
import inputStyle from './findInputStyle'
import { MentionsInput, Mention } from 'react-mentions'
import { searchPeople } from '@/handlers/api/people.handler';
import mentionStyle from './findMentionStyle';
import { PERSON_THUBNAIL_PATH } from '@/config/routes';
import Image from 'next/image';
import classNames from './FindInput.module.css';
interface FindInputProps {
onSearch: (query: string) => void;
@@ -26,13 +26,8 @@ export default function FindInput({ onSearch }: FindInputProps) {
<MentionsInput
value={query}
singleLine={true}
style={style}
className='w-full border border-gray-200 rounded-md p-2'
classNames={{
control: 'w-full border border-gray-200 rounded-md p-2',
input: 'w-full border border-gray-200 rounded-md p-2 w-full',
}}
placeholder='Search for photos, use @ to search for people'
style={inputStyle}
onKeyDown={(e) => {
if (e.key === 'Enter') {
onSearch(query);
@@ -41,14 +36,13 @@ export default function FindInput({ onSearch }: FindInputProps) {
onChange={(e) => setQuery(e.target.value)}>
<Mention
trigger="@"
data={handleSearchPeople}
style={mentionStyle}
data={handleSearchPeople}
renderSuggestion={(
highlightedDisplay,
focused
) => (
<div className={`user ${focused ? 'focused' : ''} `}>
{highlightedDisplay.display}
</div>
)}
+19 -14
View File
@@ -1,37 +1,42 @@
const findInputStyle = {
control: {
backgroundColor: '#fff',
fontSize: 14,
backgroundColor: 'hsl(var(--input))',
fontSize: 20,
fontWeight: 'normal',
},
outline: 'none',
borderRadius: '15px',
},
'&singleLine': {
display: 'inline-block',
// display: 'inline-block',
width: '100%',
highlighter: {
padding: '10px',
border: '2px inset transparent',
padding: '10px 15px',
border: 'none',
outline: 'none',
},
input: {
width: "100%",
padding: '10px',
borderRadius: '4px',
border: '1px solid #e0e0e0',
padding: '10px 15px',
border: 'none',
outline: 'none',
},
},
suggestions: {
list: {
backgroundColor: 'white',
border: '1px solid rgba(0,0,0,0.15)',
backgroundColor: 'hsl(var(--background))',
fontSize: 14,
border: '1px solid hsl(var(--border))',
overflow: 'hidden',
},
item: {
padding: '5px 15px',
borderBottom: '1px solid rgba(0,0,0,0.15)',
border: 'none',
'&focused': {
backgroundColor: '#cee4e5',
backgroundColor: 'hsl(var(--chart-2))',
},
},
},
+2 -1
View File
@@ -1,3 +1,4 @@
export default {
backgroundColor: '#cee4e5',
backgroundColor: 'hsla(var(--chart-2) / 0.3)',
position: 'relative',
}
+2 -2
View File
@@ -23,11 +23,11 @@ export default function PageLayout({ children, className, title }: IProps) {
: children;
return (
<div>
<div className="flex flex-col w-full h-full">
{header}
<main
className={cn(
"flex flex-1 max-h-[calc(100vh-60px)] flex-col gap-4 overflow-y-auto mx-auto",
"flex flex-1 max-h-[calc(100vh-60px)] flex-col gap-4 overflow-y-auto mx-auto w-full",
{
"mb-14": !!header,
},
+44 -11
View File
@@ -1,22 +1,39 @@
import "yet-another-react-lightbox/styles.css";
import FindInput from '@/components/find/FindInput';
import PageLayout from '@/components/layouts/PageLayout';
import Header from '@/components/shared/Header';
import Loader from '@/components/ui/loader';
import { ASSET_THUMBNAIL_PATH } from '@/config/routes';
import { ASSET_PREVIEW_PATH, ASSET_THUMBNAIL_PATH } from '@/config/routes';
import { useConfig } from '@/contexts/ConfigContext';
import { findAssets } from '@/handlers/api/asset.handler';
import { IAsset } from '@/types/asset';
import { Search, TriangleAlert, WandSparkles } from 'lucide-react';
import { Captions, Megaphone, Search, Speaker, TriangleAlert, WandSparkles } from 'lucide-react';
import Image from 'next/image';
import React, { useState } from 'react'
import React, { useMemo, useState } from 'react'
import Lightbox from 'yet-another-react-lightbox';
import { Button } from "@/components/ui/button";
import Link from "next/link";
export default function FindPage() {
const { geminiEnabled } = useConfig();
const [index, setIndex] = useState(-1);
const { geminiEnabled, exImmichUrl } = useConfig();
const [query, setQuery] = useState('');
const [assets, setAssets] = useState<IAsset[]>([]);
const [loading, setLoading] = useState(false);
const slides = useMemo(
() =>
assets.map((asset) => ({
src: ASSET_PREVIEW_PATH(asset.id),
width: 1000,
height: 1000,
})),
[assets]
);
const handleSearch = (query: string) => {
setQuery(query);
setLoading(true);
@@ -42,6 +59,9 @@ export default function FindPage() {
<p className='text-sm text-muted-foreground'>
Example: Sunset photos from last week. Use <kbd className='bg-zinc-200 text-black dark:text-white px-1 py-0.5 rounded-md dark:bg-zinc-500'>@</kbd> to search for photos of a specific person.
</p>
<p className='text-xs text-muted-foreground text-center flex gap-1 items-center'>
<span>Power tools uses Google Gemini only for parsing your query. None of your data is sent to Gemini.</span>
</p>
</div>
}
else if (assets.length === 0) {
@@ -50,9 +70,21 @@ export default function FindPage() {
</div>
}
return (
<>
<Lightbox
slides={slides}
open={index >= 0}
index={index}
close={() => setIndex(-1)}
/>
<div className="grid grid-cols-5 gap-4 p-2">
{assets.map((asset) => (
<div key={asset.id} className='w-full h-[200px] rounded-md overflow-hidden'>
{assets.map((asset, idx) => (
<div key={asset.id} className='w-full h-[200px] rounded-md overflow-hidden relative'>
<Link href={`${exImmichUrl}/photos/${asset.id}`}
target="_blank"
className='absolute top-2 right-2 text-xs'>
Open in Immich
</Link>
<Image
src={ASSET_THUMBNAIL_PATH(asset.id)}
alt={asset.id}
@@ -63,10 +95,12 @@ export default function FindPage() {
}}
width={200}
height={200}
onClick={() => setIndex(idx)}
/>
</div>
))}
</div>
</>
)
}
@@ -74,12 +108,12 @@ export default function FindPage() {
<PageLayout>
<Header leftComponent="Find" />
{geminiEnabled ? (
<div>
<>
<div className="flex flex-col gap-4 p-2">
<FindInput onSearch={handleSearch} />
</div>
{renderContent()}
</div>
</>
) : (
<div className="flex justify-center py-10 items-center h-full flex-col gap-2">
<WandSparkles className='w-10 h-10 text-muted-foreground' />
@@ -89,9 +123,8 @@ export default function FindPage() {
Please enable Gemini by adding <kbd className='bg-zinc-200 text-black dark:text-white px-1 py-0.5 rounded-md dark:bg-zinc-500'>GEMINI_API_KEY</kbd> in the <kbd className='bg-zinc-200 text-black dark:text-white px-1 py-0.5 rounded-md dark:bg-zinc-500'>.env</kbd> file.
</p>
<div className="border border-l-4 border-zinc-200 dark:border-zinc-500 rounded-md p-2">
<p className='text-sm text-muted-foreground text-center flex gap-1 items-center'>
<TriangleAlert className='w-4 h-4' />
<span>Power tools uses Gemini only for parsing your query. None of your data is sent to Gemini.</span>
<p className='text-xs text-muted-foreground text-center flex gap-1 items-center'>
<span>Power tools uses Google Gemini only for parsing your query. None of your data is sent to Gemini.</span>
</p>
</div>
</div>
+1 -1
View File
@@ -31,7 +31,6 @@
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
}
.dark {
@@ -88,3 +87,4 @@
--chart-5: 340 75% 55%;
}
}