Skip to content

Commit

Permalink
🧩 ui Refactor unsplash
Browse files Browse the repository at this point in the history
  • Loading branch information
steeeee0223 committed Nov 7, 2024
1 parent 0a91fc2 commit 8c44ac7
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 105 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
1. `@swy/ui/custom` → `@swy/ui/shared`
2. `@swy/ui/dnd` → `@swy/ui/shared`
3. `@swy/ui/form` → `@swy/ui/shared`
- Refactor components: `IconBlock`
- Refactor components: `IconBlock`, `Unsplash`
- Rename: `IconPicker` → `EmojiPicker`
- Remove unused shadcn components
- Remove path alias
Expand Down
3 changes: 1 addition & 2 deletions packages/ui/src/components/shared/unsplash/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export type * from "./index.types";
export * from "./unsplash-provider";
export * from "./unsplash";
7 changes: 0 additions & 7 deletions packages/ui/src/components/shared/unsplash/index.types.ts

This file was deleted.

19 changes: 0 additions & 19 deletions packages/ui/src/components/shared/unsplash/unsplash-context.tsx

This file was deleted.

28 changes: 0 additions & 28 deletions packages/ui/src/components/shared/unsplash/unsplash-provider.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { render } from "@testing-library/react";

import { Unsplash } from ".";
import { Unsplash } from "./unsplash";

describe("<Unsplash />", () => {
it("should render the default text", () => {
const ui = render(<Unsplash apiKey="" />);
expect(ui.getByPlaceholderText(/Search for an image/i)).toBeDefined();
expect(ui.getByPlaceholderText(/Search for an image/i)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
"use client";

import { useState } from "react";

import { cn } from "@swy/ui/lib";
import { Input } from "@swy/ui/shadcn";

import { Spinner } from "../spinner";
import { useUnsplash } from "./use-unsplash";

export interface UnsplashPickerProps {
export interface UnsplashProps {
/** @param apiKey - Unsplash Access Key */
apiKey: string;
className?: string;
onSelect?: (url: string) => void;
}

export const UnsplashPicker = ({
className,
onSelect,
}: UnsplashPickerProps) => {
const [query, setQuery] = useState<string>("");
const { images, isLoading } = useUnsplash({ query, count: 24 });
/**
* An `Unsplash` image browser
*/
export const Unsplash = ({ apiKey, className, onSelect }: UnsplashProps) => {
const { images, isLoading, setQuery } = useUnsplash({ apiKey });

return (
<div className={cn("max-h-[280px] w-full overflow-y-auto p-4", className)}>
<Input
id="unsplash"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search for an image..."
/>
Expand Down
86 changes: 50 additions & 36 deletions packages/ui/src/components/shared/unsplash/use-unsplash.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,61 @@
"use client";

import useSWR, { type Fetcher } from "swr";
import { useEffect, useMemo, useState, useTransition } from "react";
import { createApi } from "unsplash-js";

import { defaultImages } from "./constants";
import type { UnsplashImage } from "./index.types";
import { useUnsplashInternal } from "./unsplash-context";

export interface UnsplashConfig {
query?: string;
count?: number;
interface UnsplashImage {
id: string;
user: { name: string; portfolio_url: string };
links: { html: string };
urls: { thumb: string; full: string; regular: string; small: string };
description?: string;
}

export const useUnsplash = ({ query = "", count }: UnsplashConfig) => {
const { unsplash } = useUnsplashInternal();
const fetcher: Fetcher<UnsplashImage[], string> = async (key) => {
let search;
try {
const [, query] = key.split(":");
if (!query?.length) {
search = await unsplash.photos.getRandom({
collectionIds: ["317099"],
count,
interface UnsplashConfig {
apiKey: string;
}

export const useUnsplash = ({ apiKey }: UnsplashConfig) => {
const unsplash = useMemo(
() => createApi({ accessKey: apiKey, fetch }),
[apiKey],
);
const [query, setQuery] = useState("");
const [images, setImages] = useState<UnsplashImage[]>();
const [isLoading, startTransition] = useTransition();

useEffect(() => {
const fetchImages = async (query: string, count = 24) => {
try {
if (query.length === 0) {
const search = await unsplash.photos.getRandom({
collectionIds: ["317099"],
count,
});
if (!search.response) throw new Error("Failed to get random photos");
return search.response as UnsplashImage[];
}

const search = await unsplash.search.getPhotos({
query,
perPage: count,
});
if (!search.response) throw new Error("Failed to get random photos");
return search.response as UnsplashImage[];
if (!search.response) throw new Error(`Failed to get photos: ${query}`);
console.log(`search res: ${search.response.total}`);
return search.response.results as UnsplashImage[];
} catch (e) {
console.log("[unsplash] Failed to get images from Unsplash!");
console.log(e);
return defaultImages as UnsplashImage[];
}
};

search = await unsplash.search.getPhotos({ query, perPage: count });
if (!search.response) throw new Error(`Failed to get photos: ${query}`);
return search.response.results as UnsplashImage[];
} catch (e) {
console.log(`[unsplash] Failed to get images from Unsplash!`);
console.log(e);
return defaultImages as UnsplashImage[];
}
};
const { data, isLoading, error, mutate } = useSWR<UnsplashImage[], Error>(
`unsplash:${query}`,
fetcher,
{
onError: (e) => console.log(`[unsplash] Error: ${e.message}`),
revalidateOnFocus: false,
},
);
return { images: data, isLoading, error, mutate };
startTransition(
() => void fetchImages(query).then((images) => setImages(images)),
);
}, [unsplash, query]);

return { isLoading, images, setQuery };
};

0 comments on commit 8c44ac7

Please sign in to comment.