web: add footer and ingredients
This commit is contained in:
parent
b6a69cbeac
commit
72bb7e04cd
|
@ -6,34 +6,41 @@ export function PageLayout(ctx: Context, children: AnyNode[]): Elem {
|
||||||
return E("div", { id: "main" }, [
|
return E("div", { id: "main" }, [
|
||||||
Header(ctx),
|
Header(ctx),
|
||||||
E("div", classNames("content"), children),
|
E("div", classNames("content"), children),
|
||||||
// Footer(),
|
Footer(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Header(ctx: Context): Elem {
|
export function Header(ctx: Context): AnyNode {
|
||||||
return E("header", classNames("header"), [
|
return E("header", classNames("header"), [
|
||||||
E("div", classNames("content-width"), [HeaderNav(ctx)]),
|
E("div", classNames("content-width"), [HeaderNav(ctx)]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HeaderNav(ctx: Context): Elem {
|
export function HeaderNav(ctx: Context): AnyNode {
|
||||||
return E("nav", classNames("main-menu"), [
|
return E("nav", classNames("main-menu"), [
|
||||||
Link(navLink("/", ctx), "Главная"),
|
Link("Главная", navLink("/", ctx)),
|
||||||
Link(navLink("/recipes", ctx), "Рецепты"),
|
Link("Рецепты", navLink("/recipes", ctx)),
|
||||||
Link(navLink("/ingredients", ctx), "Ингредиенты"),
|
Link("Ингредиенты", navLink("/ingredients", ctx)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Link(attrs: Attrs | Attrs[], text: string): Elem {
|
|
||||||
return E("a", attrs, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
function navLink(href: string, ctx?: Context): Attrs {
|
function navLink(href: string, ctx?: Context): Attrs {
|
||||||
const attrs: Attrs = { href };
|
const attrs: Attrs = { href };
|
||||||
if (ctx?.locPath === href) attrs["aria-current"] = "true";
|
if (ctx?.locPath === href) attrs["aria-current"] = "true";
|
||||||
return attrs;
|
return attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Footer(): Elem {
|
export function Footer(): AnyNode {
|
||||||
return E("footer", classNames("footer"), "footer");
|
return E("footer", classNames("footer"), [
|
||||||
|
E("div", classNames("content-width"), [
|
||||||
|
Link("Исходный код", {
|
||||||
|
href: "https://notabug.org/pleshevskiy/recipes",
|
||||||
|
rel: "external nofollow noopener noreferrer",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Link(text: string, attrs: Attrs | Attrs[]): AnyNode {
|
||||||
|
return E("a", attrs, text);
|
||||||
}
|
}
|
||||||
|
|
27
web/makefile
27
web/makefile
|
@ -1,10 +1,12 @@
|
||||||
PAR := $(MAKE) -j 128
|
PAR := $(MAKE) -j 128
|
||||||
DOCKER_NAME := pleshevski
|
DOCKER_NAME := recipes
|
||||||
DOCKER_TAG := pleshevski
|
DOCKER_TAG := recipes
|
||||||
|
|
||||||
|
|
||||||
watch:
|
watch:
|
||||||
$(PAR) hr ts-w
|
deno run -A --watch server.ts
|
||||||
|
|
||||||
|
start:
|
||||||
|
deno run -A server.ts
|
||||||
|
|
||||||
docker-restart: docker-stop docker-run
|
docker-restart: docker-stop docker-run
|
||||||
|
|
||||||
|
@ -16,20 +18,3 @@ docker-run:
|
||||||
|
|
||||||
docker-build:
|
docker-build:
|
||||||
docker build -t ${DOCKER_TAG} .
|
docker build -t ${DOCKER_TAG} .
|
||||||
|
|
||||||
build: ts
|
|
||||||
|
|
||||||
start:
|
|
||||||
npm run start
|
|
||||||
|
|
||||||
hr:
|
|
||||||
deno run -A ~/sandbox/hr/server.ts target static
|
|
||||||
|
|
||||||
ts:
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
ts-w:
|
|
||||||
NODE_ENV=develop npx tsc-watch --onSuccess "make start"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf target
|
|
||||||
|
|
|
@ -11,7 +11,9 @@ export class RestIngredientRepo implements IngredientRepo {
|
||||||
|
|
||||||
const restIngrs: RestIngredient[] = await res.json();
|
const restIngrs: RestIngredient[] = await res.json();
|
||||||
|
|
||||||
return restIngrs.map(intoAppIngredient);
|
return restIngrs.map(intoAppIngredient).sort((a, b) =>
|
||||||
|
a.name.localeCompare(b.name)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,10 @@ async function handleRequest(req: Request): Promise<Response> {
|
||||||
} else if (ctx.locPath === "/ingredients") {
|
} else if (ctx.locPath === "/ingredients") {
|
||||||
const repo = new RestIngredientRepo();
|
const repo = new RestIngredientRepo();
|
||||||
const ingredients = await repo.fetchIngredients();
|
const ingredients = await repo.fetchIngredients();
|
||||||
console.log({ ingredients });
|
|
||||||
return createHtmlResponse(ren.render(IngredientsPage(ctx)));
|
return createHtmlResponse(
|
||||||
|
ren.render(IngredientsPage(ctx, { ingredients })),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return createHtmlResponse(ren.render(E404Page(ctx)), 404);
|
return createHtmlResponse(ren.render(E404Page(ctx)), 404);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,11 @@ ul, ol {
|
||||||
padding-bottom: 1.5rem;
|
padding-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.main-menu {
|
.main-menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
|
@ -3,11 +3,27 @@ import { AnyNode, E } from "ren/node.ts";
|
||||||
import { classNames } from "ren/attrs.ts";
|
import { classNames } from "ren/attrs.ts";
|
||||||
import { Context } from "../context.ts";
|
import { Context } from "../context.ts";
|
||||||
import { H3 } from "../uikit/typo.ts";
|
import { H3 } from "../uikit/typo.ts";
|
||||||
|
import { Ingredient } from "../domain/ingredient/types.ts";
|
||||||
|
|
||||||
export function IngredientsPage(ctx: Context): AnyNode {
|
interface IngredientsPageData {
|
||||||
|
ingredients: Ingredient[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IngredientsPage(
|
||||||
|
ctx: Context,
|
||||||
|
data: IngredientsPageData,
|
||||||
|
): AnyNode {
|
||||||
return PageLayout(ctx, [
|
return PageLayout(ctx, [
|
||||||
E("div", classNames("content-width"), [
|
E("div", classNames("content-width"), [
|
||||||
H3("Ингредиенты"),
|
H3("Ингредиенты"),
|
||||||
|
E("div", [], data.ingredients.map(IngredientItem)),
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function IngredientItem(ingr: Ingredient): AnyNode {
|
||||||
|
return E("div", [], [
|
||||||
|
ingr.name,
|
||||||
|
// E("a", { href: `/ingredients/${ingr.key}` }, ingr.name),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue