@@ -435,13 +448,15 @@ export default function SearchResultsPage() {
Treff for «{searchTerm}»
{storeHeading}
>
+ ) : hasCategorySelection ? (
+ "Produkter i valgte kategorier"
) : (
- "Søk etter matvarer"
+ "Produktkatalog"
)}
- {hasSearch && !loading && !error
+ {shouldFetchProducts && !loading && !error
? `${totalProducts} produkter funnet`
: "Søkeresultater"}
@@ -499,6 +514,7 @@ export default function SearchResultsPage() {
@@ -588,11 +604,7 @@ export default function SearchResultsPage() {
: undefined,
}}
>
- {!hasSearch ? (
-
- Skriv inn et søkeord for å finne matvarer.
-
- ) : loading ? (
+ {loading ? (
Laster produkter...
) : error ? (
diff --git a/frontend/src/pages/home/HomePage.css b/frontend/src/pages/home/HomePage.css
index 4f4e1f4..4eb7e5c 100644
--- a/frontend/src/pages/home/HomePage.css
+++ b/frontend/src/pages/home/HomePage.css
@@ -299,4 +299,34 @@
.categories__grid {
grid-template-columns: 1fr;
}
+
+
+ .home__hero {
+ grid-template-columns: minmax(0, 1fr);
+ }
+
+ .hero {
+ min-width: 0;
+ width: 100%;
+ }
+
+ .hero__lead {
+ min-width: 0;
+ max-width: 100%;
+ overflow-wrap: break-word;
+ }
+
+ .active-note {
+ width: 100%;
+ min-width: 0;
+ }
+
}
+
+/* Unngå at den dekorative lappen gir horisontal scrolling */
+@media (max-width: 600px) {
+ .active-note__back {
+ right: 4px;
+ transform: rotate(2deg);
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/pages/home/HomePage.tsx b/frontend/src/pages/home/HomePage.tsx
index a557a81..c1c709e 100644
--- a/frontend/src/pages/home/HomePage.tsx
+++ b/frontend/src/pages/home/HomePage.tsx
@@ -1,3 +1,12 @@
+
+import type { FormEvent } from "react";
+
+import { gql } from "@apollo/client";
+import type { TypedDocumentNode } from "@apollo/client";
+import { useQuery } from "@apollo/client/react";
+
+import { homeCategories } from "./homeCategories";
+
import "./HomePage.css";
import "../../components/searchfield/Searchfield.css";
import "../../components/button/Button.css";
@@ -5,7 +14,11 @@ import "../../components/noteItem/NoteItem.css";
import "../../components/checkbox/Checkbox.css";
import "../../components/categoryCard/CategoryCard.css";
-// Midlertidige data. Byttes ut med ekte data fra backend senere.
+// ==========================================
+// MIDLERTIDIG HANDLELAPP
+// Erstattes med ekte handlelistedata senere.
+// ==========================================
+
const noteItems = [
{ name: "Lettmelk", count: "×2" },
{ name: "Norvegia 26 %" },
@@ -14,35 +27,119 @@ const noteItems = [
{ name: "Tomater", count: "×4" },
];
-const categories = [
- {
- name: "Frukt og grønt",
- description: "Frukt, grønnsaker, urter",
- count: 214,
- },
- { name: "Meieri og egg", description: "Melk, yoghurt, egg", count: 96 },
- { name: "Ost", description: "Hvitost, brunost, smøreost", count: 148 },
- {
- name: "Brød og bakst",
- description: "Brød, knekkebrød, lefser",
- count: 122,
- },
- {
- name: "Kjøtt og fisk",
- description: "Kylling, kjøttdeig, laks",
- count: 187,
- },
- { name: "Tørrvarer", description: "Pasta, ris, havregryn", count: 263 },
- { name: "Frysevarer", description: "Pizza, grønnsaker, is", count: 91 },
- { name: "Drikke", description: "Kaffe, te, juice", count: 175 },
-];
+// ==========================================
+// GRAPHQL – KATEGORIER OG PRODUKTANTALL
+// ==========================================
+
+type CategoryCount = {
+ value: string;
+ label: string;
+ count: number;
+};
+
+type CategoryCountsData = {
+ categoryFilterCounts: CategoryCount[];
+};
+
+const HOME_CATEGORY_COUNTS_QUERY: TypedDocumentNode<
+ CategoryCountsData
+> = gql`
+ query HomeCategoryCounts {
+ categoryFilterCounts {
+ value
+ label
+ count
+ }
+ }
+`;
+
+// ==========================================
+// PROPS
+// ==========================================
+
+type HomePageProps = {
+ onSearch: (value: string) => void;
+ onCategorySelect: (categoryIds: string[]) => void;
+};
+
+// ==========================================
+// HJEMMESIDE
+// ==========================================
+
+function HomePage({
+ onSearch,
+ onCategorySelect,
+}: HomePageProps) {
+ // Henter faktiske produktantall fra GraphQL.
+ const {
+ data: categoryData,
+ loading: categoriesLoading,
+ error: categoriesError,
+ } = useQuery(HOME_CATEGORY_COUNTS_QUERY);
+
+ const categoryCounts =
+ categoryData?.categoryFilterCounts ?? [];
+
+
+ const categories = homeCategories
+ .flatMap((category) => {
+ const matchingCategory = categoryCounts.find(
+ (item) =>
+ item.label.toLocaleLowerCase("nb-NO") ===
+ category.name.toLocaleLowerCase("nb-NO"),
+ );
+
+ if (!matchingCategory) {
+ return [];
+ }
+
+ return [
+ {
+ name: category.name,
+ description: category.description,
+ categoryIds: [matchingCategory.value],
+ count: matchingCategory.count,
+ },
+ ];
+ })
+ .sort((a, b) =>
+ a.name.localeCompare(b.name, "nb-NO"),
+ );
+
+ // ==========================================
+ // SØK FRA STARTSIDEN
+ // ==========================================
+
+ const handleSearchSubmit = (
+ event: FormEvent,
+ ) => {
+ event.preventDefault();
+
+ const formData = new FormData(event.currentTarget);
+ const search = String(
+ formData.get("search") ?? "",
+ ).trim();
+
+ if (search) {
+ onSearch(search);
+ }
+ };
+
+ // ==========================================
+ // RENDER
+ // ==========================================
-function HomePage() {
return (
+ {/* ======================================
+ HERO – OVERSKRIFT OG SØKEFELT
+ ====================================== */}
+
-
HANDLELAPPEN · VOL. 01 · HØST 2026
+
+ HANDLELAPPEN · VOL. 01 · HØST 2026
+
Hva skal på
@@ -50,19 +147,33 @@ function HomePage() {
- Søk etter en vare, eller bla deg gjennom en kategori. Lappen holder
- styr på resten, og viser hva det koster i hver kjede.
+ Søk etter en vare, eller bla deg gjennom en kategori.
+ Lappen holder styr på resten, og viser hva det
+ koster i hver kjede.
-
@@ -71,19 +182,45 @@ function HomePage() {
12 400 VARER · 6 KJEDER · OPPDATERT DAGLIG
-