Skip to content

Commit

Permalink
refactor website
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosqsilva committed Sep 3, 2024
1 parent bcbe999 commit 50980b6
Show file tree
Hide file tree
Showing 17 changed files with 513 additions and 250 deletions.
19 changes: 12 additions & 7 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,23 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/check": "^0.9.1",
"@astrojs/solid-js": "^4.4.0",
"@astrojs/check": "^0.9.3",
"@astrojs/solid-js": "^4.4.1",
"@astrojs/tailwind": "^5.1.0",
"@tanstack/solid-virtual": "^3.8.4",
"astro": "^4.13.1",
"@tanstack/solid-virtual": "^3.10.6",
"astro": "^4.15.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"date-fns": "^3.6.0",
"debounce": "^2.1.0",
"lucide-solid": "^0.438.0",
"minisearch": "^7.1.0",
"nanoid": "^5.0.7",
"solid-js": "^1.8.19",
"tailwind-merge": "^2.4.0",
"tailwindcss": "^3.4.7",
"query-string": "^9.1.0",
"solid-js": "^1.8.22",
"tailwind-merge": "^2.5.2",
"tailwindcss": "^3.4.10",
"tinykeys": "^3.0.0",
"typescript": "^5.5.3"
}
}
22 changes: 0 additions & 22 deletions app/src/components/logo.tsx

This file was deleted.

162 changes: 0 additions & 162 deletions app/src/components/search.tsx

This file was deleted.

48 changes: 48 additions & 0 deletions app/src/components/search/filterOptions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { createSelector, For } from "solid-js";
import { Button } from "../ui/button";
import { searchStore } from "./state";
import { RotateCcw } from "lucide-solid";

interface OptionsFiltersProps {
options: Array<{ label: string; value: string }>;
onChange?: (options: string[]) => void;
}

export function FilterOptions(props: OptionsFiltersProps) {
const isSelected = createSelector<string[], string>(
() => searchStore.searchFilter,
(value, options) => new Set(options).has(value),
);

const onChange = (option: string) => {
const selected = new Set(searchStore.searchFilter);
selected.has(option) ? selected.delete(option) : selected.add(option);
props.onChange?.([...selected]);
};

return (
<div class="space-y-2">
<For each={props.options}>
{(item) => (
<label class="flex items-center select-none">
<input
type="checkbox"
value={item.value}
class="w-4 h-4 bg-gray-100 border-gray-300 rounded text-neutral-900 focus:ring-neutral-900"
checked={isSelected(item.value)}
onChange={[onChange, item.value]}
/>
<span class="ml-2 text-sm font-medium text-gray-900">
{item.label}
</span>
</label>
)}
</For>

<Button class="w-full" onClick={() => props.onChange?.([])}>
<RotateCcw size={18} />
Reset Filter
</Button>
</div>
);
}
113 changes: 113 additions & 0 deletions app/src/components/search/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { onMount, Show } from "solid-js";
import qs from "query-string";

import { Results } from "./results";
import {
setSearchStore,
resultStore,
searchStore,
debouncedSearch,
} from "./state";
import { defined } from "../../utils";
import { Logo } from "../ui/logo";
import { FilterOptions } from "./filterOptions";
import { SearchInput } from "./searchInput";

export function Search() {
onMount(() => {
const { q, s = [] } = qs.parse(window.location.search, {
types: {
q: "string",
s: "string[]",
},
}) as { q: string; s: string[] };

if (defined(q) && q !== "") {
setSearchStore({
searchQuery: q,
searchFilter: s,
searchView: true,
});

debouncedSearch.trigger();
}
});

return (
<Show when={searchStore.searchView} fallback={<SearchEmpty />}>
<SearchResult />
</Show>
);
}

function SearchEmpty() {
return (
<div class="px-8 max-w-screen-lg mx-auto min-h-[80vh] flex flex-col gap-10 items-center justify-center">
<Logo size="lg" />

<p class="text-xl text-zinc-600">
Search curated content from 7 programming newsletter
</p>

<SearchInput class="w-full" />
</div>
);
}

function SearchResult() {
return (
<div class="h-screen flex flex-col">
<header class="px-4 border-b">
<div class="py-10 container mx-auto flex items-center gap-8">
<Logo />

<SearchInput class="flex-1" />
</div>
</header>

<div class="px-4 flex-1 bg-zinc-50">
<main class="flex gap-8 h-full container mx-auto">
<div class="max-w-56 py-10 px-4">
<FilterOptions
onChange={(filters) => {
setSearchStore("searchFilter", filters);
debouncedSearch.trigger();
}}
options={[
{ label: "Node Weekly", value: "nodeweekly" },
{ label: "JavaScript Weekly", value: "javascriptweekly" },
{ label: "Frontend Focus", value: "frontendfocus" },
{ label: "React Status", value: "reactstatus" },
{ label: "This Week in React", value: "thisweekinreact" },
{ label: "Golang Weekly", value: "golangweekly" },
{ label: "Ruby Weekly", value: "rubyweekly" },
{ label: "Postgres Weekly", value: "postgresweekly" },
]}
/>
</div>

<div class="flex-1 flex flex-col">
<Show when={resultStore.results.length > 0}>
<div class="pt-5 text-zinc-800">
Found{" "}
<span class="font-semibold">{resultStore.results.length}</span>{" "}
items in {resultStore.searchTime} ms
</div>
</Show>

<Show when={resultStore.empty}>
<div class="pt-32 text-zinc-800 flex flex-col gap-4 items-center justify-center text-center">
<div class="text-7xl">🫠</div>
<span class="text-2xl">
Nothing Found for: '{searchStore.searchQuery}'
</span>
</div>
</Show>

<Results />
</div>
</main>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ export function Result(props: {
href={props.result.url}
target="_blank"
rel="noreferrer"
class="p-4 py-5 hover:underline underline-offset-4 decoration-slate-200"
class="p-4 py-5 hover:underline underline-offset-4 decoration-zinc-400"
>
<p class="text-lg text-slate-200">{props.result.description}</p>
<div class="text-slate-400">
<p class="text-lg text-zinc-700">{props.result.description}</p>
<div class="text-zinc-500">
{props.result.date} | {props.result.source}
</div>
</a>
Expand Down
Loading

0 comments on commit 50980b6

Please sign in to comment.