Archived
concerts page
This commit is contained in:
9 files changed
+154
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 758 KiB |
@@ -0,0 +1,50 @@
|
||||
.container {
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--background);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
border-radius: 20px;
|
||||
|
||||
i {
|
||||
color: var(--accent);
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
h1 {
|
||||
color: var(--accent);
|
||||
margin: 0;
|
||||
}
|
||||
> strong {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.buyTicket {
|
||||
margin-top: 20px;
|
||||
padding: 10px 20px;
|
||||
border: 0;
|
||||
border-radius: 10px;
|
||||
background-color: var(--accent);
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
|
||||
&.unavailable {
|
||||
background-color: #ccc;
|
||||
cursor: no-drop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
i {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Component } from "solid-js";
|
||||
import { languageStore } from "../../stores/language";
|
||||
import style from "./index.module.scss";
|
||||
import { Concert } from "../../types/data";
|
||||
import { Icon } from "../icon";
|
||||
import { useDictionary } from "../../dictionaries";
|
||||
import clsx from "clsx";
|
||||
import { A } from "@solidjs/router";
|
||||
|
||||
export const ConcertEntry: Component<Concert> = (props) => {
|
||||
const [lang] = languageStore;
|
||||
const st = useDictionary();
|
||||
|
||||
return (
|
||||
<div class={style.container}>
|
||||
<Icon size={2.5} name="calendar3" />
|
||||
<div class={style.info}>
|
||||
<h1>{props.eventName}</h1>
|
||||
<strong>
|
||||
{new Date(props.date).toLocaleDateString(lang() === "en" ? "en-US" : "pl-PL", {
|
||||
dateStyle: "full",
|
||||
})}
|
||||
</strong>
|
||||
<p>
|
||||
{props.place}{" "}
|
||||
<strong>{`${lang() === "en" ? "from" : "od"} ${props.ticketPrice.toLocaleString(
|
||||
lang() === "en" ? "en-US" : "pl-PL",
|
||||
{ style: "currency", currency: "PLN" }
|
||||
)}`}</strong>
|
||||
</p>
|
||||
<A href="/checkout">
|
||||
<button
|
||||
class={clsx(style.buyTicket, {
|
||||
[style.unavailable]: !props.ticketsAvailable,
|
||||
})}
|
||||
disabled={!props.ticketsAvailable}
|
||||
>
|
||||
{st()["CONCERTS_BUY_TICKET"]}
|
||||
</button>
|
||||
</A>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -5,4 +5,5 @@ export const englishStringTable: StringTable = {
|
||||
NAV_MERCH: "store",
|
||||
HOME_TITLE: "Inverse band",
|
||||
HOME_DESCRIPTION: "Lorem ipsum EN",
|
||||
CONCERTS_BUY_TICKET: "Buy ticket",
|
||||
};
|
||||
@@ -8,6 +8,7 @@ export type StringTable = {
|
||||
NAV_MERCH: string;
|
||||
HOME_TITLE: string;
|
||||
HOME_DESCRIPTION: string;
|
||||
CONCERTS_BUY_TICKET: string;
|
||||
};
|
||||
|
||||
export const useDictionary = () => {
|
||||
|
||||
@@ -5,4 +5,5 @@ export const polishStringTable: StringTable = {
|
||||
NAV_MERCH: "sklep",
|
||||
HOME_TITLE: "Zespół Inverse",
|
||||
HOME_DESCRIPTION: "Lorem ipsum PL",
|
||||
CONCERTS_BUY_TICKET: "Kup bilet",
|
||||
};
|
||||
@@ -10,6 +10,7 @@ import { useDictionary } from "./dictionaries";
|
||||
import { createEffect, onMount } from "solid-js";
|
||||
import { languageStore } from "./stores/language";
|
||||
import { Store } from "./pages/store";
|
||||
import { Concerts } from "./pages/concerts";
|
||||
|
||||
const root = document.getElementById("root");
|
||||
|
||||
@@ -54,6 +55,7 @@ render(() => {
|
||||
<main>
|
||||
<Routes>
|
||||
<Route path={"/store"} element={<Store />} />
|
||||
<Route path={"/concerts"} element={<Concerts />} />
|
||||
<Route path={"/"} element={<Home />} />
|
||||
</Routes>
|
||||
</main>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
.page {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-image: url("/concerts.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Component, Show, createSignal, onMount } from "solid-js";
|
||||
import style from "./index.module.scss";
|
||||
import { ContentBox } from "../../components/ContentBox";
|
||||
import { Concert, ConcertsData } from "../../types/data";
|
||||
import { LoadingSpinner } from "../../components/LoadingSpinner";
|
||||
import { ErrorComponent } from "../../components/Error";
|
||||
import { ConcertEntry } from "../../components/Concert";
|
||||
|
||||
export const Concerts: Component = () => {
|
||||
const [data, setData] = createSignal<Concert[]>();
|
||||
const [error, setError] = createSignal<string>();
|
||||
|
||||
onMount(async () => {
|
||||
const rq = await fetch("/data/concerts.json").catch(() => {
|
||||
setError("Nie udało się połączyć z serwerem");
|
||||
});
|
||||
if (!rq) return;
|
||||
if (rq.status !== 200) {
|
||||
setError(`Podczas pobierania danych wystąpił błąd (${rq.status})`);
|
||||
return;
|
||||
}
|
||||
const { concerts } = (await rq.json()) as ConcertsData;
|
||||
setData(concerts);
|
||||
});
|
||||
|
||||
if (error() !== undefined) {
|
||||
return <ErrorComponent details={error()!} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div class={style.page}>
|
||||
<ContentBox>
|
||||
<Show
|
||||
when={Array.isArray(data())}
|
||||
fallback={
|
||||
<div style={{ display: "flex", "justify-content": "center" }}>
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{data()?.map((c) => (
|
||||
<ConcertEntry {...c} />
|
||||
))}
|
||||
</Show>
|
||||
</ContentBox>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in new issue
Block a user