Created
November 22, 2020 06:08
-
-
Save Lulzx/62a39ce0a22a259eb743c5d3f4b189fe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script lang="ts"> | |
import { metatags } from "@roxi/routify"; | |
import Theme from "./components/Theme.svelte"; | |
import { | |
Content, | |
ContentSwitcher, | |
DataTable, | |
Form, | |
FormGroup, | |
Header, | |
HeaderGlobalAction, | |
HeaderUtilities, | |
Icon, | |
PaginationNav, | |
Search, | |
Switch, | |
StructuredList, | |
StructuredListHead, | |
StructuredListRow, | |
StructuredListCell, | |
StructuredListBody, | |
} from "carbon-components-svelte"; | |
import { onMount } from "svelte"; | |
import Sun24 from "carbon-icons-svelte/lib/Sun24"; | |
import Moon24 from "carbon-icons-svelte/lib/Moon24"; | |
import Calendar24 from "carbon-icons-svelte/lib/Calendar24"; | |
import Network_224 from "carbon-icons-svelte/lib/Network_224"; | |
import UserProfile24 from "carbon-icons-svelte/lib/UserProfile24"; | |
import CheckmarkFilled16 from "carbon-icons-svelte/lib/CheckmarkFilled16"; | |
import InformationSquare24 from "carbon-icons-svelte/lib/InformationSquare24"; | |
import { TornadoWarning16 } from "carbon-icons-svelte"; | |
metatags.title = "Shoten Search"; | |
metatags.description = "Book search engine"; | |
let ref: HTMLInputElement; | |
let theme: string; | |
let page: any = 0; | |
let pages: number = 1; | |
let rows: any[] = []; | |
let total: number; | |
let type: string = "title"; | |
let state: string = "onload"; | |
let autofocus: boolean = true; | |
const themes: string[] = ["g10", "g100"]; | |
let types: string[] = ["title", "author", "publisher", "year"]; | |
let headers: string[] = [...types, "size", "extension"]; | |
let previous_page: number = 0; | |
let current_query: string = ""; | |
let previous_query: string = ""; | |
let icons = [InformationSquare24, UserProfile24, Network_224, Calendar24]; | |
const persisted_theme: string = localStorage.getItem("theme"); | |
if (themes.indexOf(persisted_theme) > -1) { | |
theme = persisted_theme; | |
} else { | |
if (window.matchMedia) { | |
const darkModeOn = window.matchMedia("(prefers-color-scheme: dark)"); | |
theme = darkModeOn.matches ? "g100" : "g10"; | |
} | |
} | |
let dark: boolean = theme === "g100"; | |
let theme_icon = !dark ? Sun24 : Moon24; | |
function toggle_theme(): void { | |
theme = dark ? "g10" : "g100"; | |
theme_icon = dark ? Sun24 : Moon24; | |
dark = !dark; | |
ref.focus(); | |
} | |
async function retrieve<T>(request: RequestInfo): Promise<T> { | |
const response = await fetch(request); | |
const body = await response.json(); | |
return body; | |
} | |
interface info { | |
results: []; | |
count: string; | |
} | |
const search = async () => { | |
if (!current_query) { | |
return; | |
} | |
state = "loading"; | |
let current_page = page + 1; | |
if (!page) { | |
current_page = 1; | |
} | |
if (previous_page === current_page && previous_query === current_query) { | |
state = "completed"; | |
return; | |
} | |
if (previous_query !== current_query) { | |
current_page = 1; | |
page = 0; | |
} | |
let base_url: string = "https://lulzx.herokuapp.com/query/"; | |
let url: string = | |
base_url + type + "/" + current_query + "/" + current_page; | |
const data = await retrieve<info[]>(url); | |
rows = data["results"]; | |
total = data["count"]; | |
if (total <= 25) { | |
pages = 1; | |
} else { | |
pages = ~~(total / 25); | |
} | |
let nextState = "?" + type + "=" + current_query; | |
window.history.replaceState("", "", nextState); | |
previous_page = current_page; | |
previous_query = current_query; | |
state = "completed"; | |
}; | |
function mobile() { | |
return typeof window.orientation !== "undefined"; | |
} | |
onMount(async () => { | |
if (typeof window != "undefined") { | |
let location = new URL(window.location.href); | |
if (location.search !== "") { | |
let current_type: string; | |
state = "loading"; | |
for (let x of types) { | |
if (location.searchParams.has(x)) { | |
current_type = x; | |
type = current_type; | |
break; | |
} | |
} | |
current_query = location.searchParams.get(current_type); | |
await search(); | |
} | |
let url = "https://lulzx.herokuapp.com/"; | |
await fetch(url) | |
.then(() => { | |
console.log("feels good man!"); | |
}) | |
.catch((error) => { | |
console.error(error); | |
}); | |
ref.focus(); | |
} | |
}); | |
</script> | |
<style> | |
h1 { | |
display: flex; | |
padding-top: 15vmin; | |
justify-content: center; | |
text-align: center; | |
position: relative; | |
font-weight: bold; | |
font-size: 15vw; | |
min-width: auto; | |
text-shadow: 0.03em 0.03em 0 rgb(15, 98, 254); | |
} | |
h1:after { | |
content: attr(data-shadow); | |
position: absolute; | |
right: 0; | |
min-width: auto; | |
padding-top: 0.06em; | |
left: 0.06em; | |
z-index: -1; | |
text-shadow: none; | |
background-image: linear-gradient( | |
45deg, | |
transparent 45%, | |
rgb(51, 51, 51) 45%, | |
rgb(44, 44, 44) 55%, | |
transparent 0 | |
); | |
background-size: 0.05em 0.05em; | |
background-clip: initial; | |
-webkit-background-clip: text; | |
-webkit-text-fill-color: transparent; | |
animation: shad-anim 30s linear infinite; | |
} | |
@keyframes shad-anim { | |
0% { | |
background-position: 0 0; | |
} | |
0% { | |
background-position: 100% -100%; | |
} | |
} | |
:global(.bx--header) { | |
background-color: #161616; | |
} | |
:global(.bx--header__action) { | |
padding: revert; | |
} | |
:global(.bx--header__action:focus) { | |
border-color: #161616; | |
} | |
:global(.bx--header__action:hover) { | |
background-color: #161616; | |
} | |
:global(.bx--content) { | |
background: none; | |
padding: 1.5rem; | |
} | |
:global(.bx--fieldset) { | |
min-width: auto; | |
} | |
</style> | |
{#if ['onload', 'completed'].includes(state)} | |
<Theme persist bind:theme> | |
<Header | |
company="Shoten" | |
platformName="Book Search Engine" | |
on:click={() => { | |
window.location.href = '/'; | |
}} | |
href="/"> | |
<HeaderUtilities> | |
<HeaderGlobalAction | |
aria-label="toggle theme" | |
icon={theme_icon} | |
on:click={toggle_theme} /> | |
</HeaderUtilities> | |
</Header> | |
{#if state === 'onload'} | |
<h1 data-shadow="Shoten">Shoten</h1> | |
{/if} | |
<Content> | |
<Form on:submit={search}> | |
<Search | |
bind:ref | |
bind:value={current_query} | |
placeholder="type book {type}..." | |
bind:autofocus /> | |
</Form> | |
<FormGroup legendText="Filter (fields)"> | |
<ContentSwitcher selectedIndex={types.indexOf(type)}> | |
{#each types as k} | |
<Switch | |
on:mouseleave={() => { | |
ref.focus(); | |
}} | |
on:click={() => { | |
type = k; | |
}}> | |
<div style="display: flex; align-items: center;"> | |
<Icon render={icons[types.indexOf(k)]} /> | |
{k} | |
</div> | |
</Switch> | |
{/each} | |
</ContentSwitcher> | |
</FormGroup> | |
{#if state === 'completed'} | |
{#if mobile()} | |
<StructuredList> | |
<StructuredListHead> | |
<StructuredListRow head> | |
{#each types as type} | |
<StructuredListCell head>{type}</StructuredListCell> | |
{/each} | |
</StructuredListRow> | |
</StructuredListHead> | |
<StructuredListBody> | |
{#each rows as row} | |
<StructuredListRow> | |
<StructuredListCell>{row.title}</StructuredListCell> | |
<StructuredListCell>{row.author}</StructuredListCell> | |
<StructuredListCell>{row.publisher}</StructuredListCell> | |
<StructuredListCell>{row.year}</StructuredListCell> | |
</StructuredListRow> | |
{/each} | |
</StructuredListBody> | |
</StructuredList> | |
{:else} | |
<DataTable | |
sortable | |
zebra | |
on:click:row={({ detail }) => { | |
let str = detail['download'], | |
hash = str.split('main/')[1], | |
book_url = window.location.origin + '/book?id=' + hash; | |
window.open(book_url, '_blank'); | |
}} | |
title="Search Results" | |
description="A total of {total} results were found for your query." | |
headers={headers.map((x) => ({ key: x, value: x }))} | |
{rows} /> | |
<PaginationNav | |
bind:page | |
on:change={search} | |
total={pages} | |
on:click:button--previous={page} | |
on:click:button--next={page} /> | |
{/if} | |
{/if} | |
</Content> | |
</Theme> | |
{:else if state === 'loading'} | |
<div id="search" /> | |
{/if} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment