Skip to content

Commit

Permalink
chore: Remove unused dependencies and update cache handling in Search…
Browse files Browse the repository at this point in the history
…Results component
  • Loading branch information
bramses committed Sep 6, 2024
1 parent 07f60d4 commit 8488f47
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 85 deletions.
23 changes: 18 additions & 5 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ export default withSentryConfig(
experimental: {
serverComponentsExternalPackages: ['@electric-sql/pglite'],
},
devIndicators: {
autoPrerender: false, // Disable auto-prerendering
},
async headers() {
return [
{
source: '/ws',
headers: [
{
key: 'Upgrade',
value: 'websocket',
},
],
},
];
},
}),
),
{
Expand All @@ -46,11 +62,8 @@ export default withSentryConfig(
// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,

// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
// This can increase your server load as well as your hosting bill.
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
// side errors will fail.
tunnelRoute: '/monitoring',
// Disable tunnel route for Sentry to avoid WebSocket issues
tunnelRoute: false,

// Hides source maps from generated client bundles
hideSourceMaps: true,
Expand Down
12 changes: 1 addition & 11 deletions sentry.client.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from '@sentry/nextjs';
import * as Spotlight from '@spotlightjs/spotlight';

Sentry.init({
// Sentry DSN
Expand All @@ -20,17 +19,8 @@ Sentry.init({
// This sets the sample rate to be 10%. You may want this to be 100% while
// in development and sample at a lower rate in production
replaysSessionSampleRate: 0.1,

// You can remove this option if you're not planning to use the Sentry Session Replay feature:
integrations: [
Sentry.replayIntegration({
// Additional Replay configuration goes in here, for example:
maskAllText: true,
blockAllMedia: true,
}),
],
});

if (process.env.NODE_ENV === 'development') {
Spotlight.init();
// Spotlight.init();
}
5 changes: 5 additions & 0 deletions src/app/[locale]/(auth)/dashboard/collections/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Collection = () => {
return <div>Collection</div>;
};

export default Collection;
5 changes: 5 additions & 0 deletions src/app/[locale]/(auth)/dashboard/collections/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Collections = () => {
return <div>Collections (a permanent playlist of entries)</div>;
};

export default Collections;
244 changes: 175 additions & 69 deletions src/components/SearchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,39 @@ const SearchResults = () => {
const [textAreaValue, setTextAreaValue] = useState('');
const [showLoading, setShowLoading] = useState(false);
const [searchResults, setSearchResults] = useState<any[]>([]);
const [checkedButtons, setCheckedButtons] = useState<{
[key: string]: boolean;
}>({});
const [buildingCollection, setBuildingCollection] = useState(false);

const addToCollection = (id: string, title: string) => {
// add to collection
// check if the id is already in the collection and skip if it is
if (localStorage.getItem('buildingCollection')) {
const collection = JSON.parse(
localStorage.getItem('buildingCollection') as string,
);
if (collection.find((entry: any) => entry.id === id)) {
return;
}
collection.push({
id,
title,
link: `https://ycb-companion.onrender.com/dashboard/entry/${id}`,
});
localStorage.setItem('buildingCollection', JSON.stringify(collection));
} else {
localStorage.setItem(
'buildingCollection',
JSON.stringify([{ id, title }]),
);
}
setCheckedButtons((prev) => ({
...prev,
[id]: !prev[id],
}));
};

const searchParams = useSearchParams();
// const router = useRouter();
const pathname = usePathname();
Expand Down Expand Up @@ -81,6 +114,13 @@ const SearchResults = () => {
}
}, [searchParams]);

// check local storage for collection being built (ar array of objects)
useEffect(() => {
if (localStorage.getItem('buildingCollection')) {
setBuildingCollection(true);
}
}, []);

// when searchResults change, append to cache
useEffect(() => {
if (searchResults.length > 0)
Expand Down Expand Up @@ -176,84 +216,150 @@ const SearchResults = () => {
{rndmBtnText}
</button>
</div>
{/* download collection btn only if buildingCollection is true */}
{buildingCollection && (
<button
type="button"
onClick={() => {
// clear the buildingCollection key from localStorage and download the collection as a json file
const collection = JSON.parse(
localStorage.getItem('buildingCollection') as string,
);
const blob = new Blob([JSON.stringify(collection)], {
type: 'application/json',
});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `collection-${new Date().toISOString()}.json`;
a.click();
URL.revokeObjectURL(url);
localStorage.removeItem('buildingCollection');
setBuildingCollection(false);
}}
className="mb-2 me-2 mt-4 w-full rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Download Collection
</button>
)}
{showLoading && <div>Loading...</div>}
{searchResults.map((result) => (
<div key={result.id} className="mb-4">
<Link
href={{
pathname: `/dashboard/entry/${result.id}`,
}}
className="block"
onClick={() => {
window.history.pushState(
{},
'',
createQueryString('query', textAreaValue, pathname),
);
}}
>
<div className="flex items-center text-blue-600 hover:underline">
<Image
src={result.favicon}
alt="favicon"
width={16}
height={16}
className="mr-2"
/>
<span className="font-medium">
{result.data.split(' ').length > 12 ? (
<>
{splitIntoWords(result.data, 12, 0)}...
<span className="mt-1 block text-sm text-gray-500">
...{splitIntoWords(result.data, 20, 12)}...
</span>
</>
) : (
result.data
<div key={result.id} className="mb-4 flex items-center justify-between">
<div className="grow">
<Link
href={{
pathname: `/dashboard/entry/${result.id}`,
}}
className="block"
onClick={() => {
window.history.pushState(
{},
'',
createQueryString('query', textAreaValue, pathname),
);
}}
>
<div className="flex items-center text-blue-600 hover:underline">
<Image
src={result.favicon}
alt="favicon"
width={16}
height={16}
className="mr-2"
/>
<span className="font-medium">
{result.data.split(' ').length > 12 ? (
<>
{splitIntoWords(result.data, 12, 0)}...
<span className="mt-1 block text-sm text-gray-500">
...{splitIntoWords(result.data, 20, 12)}...
</span>
</>
) : (
result.data
)}
</span>
</div>
<div className="text-sm text-gray-500">
{result.parentData && (
<span className="mt-1 block">{result.parentData.data}</span>
)}
</span>
</div>
</div>
</Link>
<div className="text-sm text-gray-500">
{result.parentData && (
<span className="mt-1 block">{result.parentData.data}</span>
Created: {new Date(result.createdAt).toLocaleString()}
{result.createdAt !== result.updatedAt && (
<>
{' '}
| Last Updated: {new Date(
result.updatedAt,
).toLocaleString()}{' '}
</>
)}
</div>
</Link>
{/* when was the entry created and updated */}
<div className="text-sm text-gray-500">
Created: {new Date(result.createdAt).toLocaleString()}
{result.createdAt !== result.updatedAt && (
<>
{' '}
| Last Updated: {new Date(
result.updatedAt,
).toLocaleString()}{' '}
</>
)}
<a
target="_blank"
href={result.metadata.author}
rel="noopener noreferrer"
className="inline-flex items-center font-medium text-blue-600 hover:underline"
>
{toHostname(result.metadata.author)}
<svg
className="ms-2.5 size-3 rtl:rotate-[270deg]"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 18 18"
>
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M15 11v4.833A1.166 1.166 0 0 1 13.833 17H2.167A1.167 1.167 0 0 1 1 15.833V4.167A1.166 1.166 0 0 1 2.167 3h4.618m4.447-2H17v5.768M9.111 8.889l7.778-7.778"
/>
</svg>
</a>
</div>
<a
target="_blank"
href={result.metadata.author}
rel="noopener noreferrer"
className="inline-flex items-center font-medium text-blue-600 hover:underline"
<button
type="button"
className={`ml-4 rounded-full p-2 text-white focus:outline-none focus:ring-2 focus:ring-blue-300 ${
checkedButtons[result.id] ? 'bg-green-500' : 'bg-blue-500'
}`}
onClick={() => addToCollection(result.id, result.data)}
>
{toHostname(result.metadata.author)}
<svg
className="ms-2.5 size-3 rtl:rotate-[270deg]"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 18 18"
>
<path
{checkedButtons[result.id] ? (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
className="size-5"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M5 13l4 4L19 7"
/>
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M15 11v4.833A1.166 1.166 0 0 1 13.833 17H2.167A1.167 1.167 0 0 1 1 15.833V4.167A1.166 1.166 0 0 1 2.167 3h4.618m4.447-2H17v5.768M9.111 8.889l7.778-7.778"
/>
</svg>
</a>
className="size-5"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M12 4v16m8-8H4"
/>
</svg>
)}
</button>
</div>
))}
</div>
Expand Down

0 comments on commit 8488f47

Please sign in to comment.