Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .github/dependabot.yml

This file was deleted.

9 changes: 9 additions & 0 deletions components/Checkout/CheckoutForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,20 @@ import { BILLING_FIELDS, BILLING_SCHEMA } from "./constants/BILLING_FIELDS";

import CHECKOUT_MUTATION from "@/apollo/mutations/CHECKOUT_MUTATION.gql";

/**
* Returns an input string with its first character capitalized.
*
* @param {string} input - The string to capitalize the first character of.
* @return {string} The input string with the first character capitalized.
*/
const upperCaseFirstChar = (input) =>
input.charAt(0).toUpperCase() + input.slice(1);

const paymentMethod = "cod";

/**
* Handles the submission of a checkout form with the provided user information.
*/
const handleSubmit = ({
firstName,
lastName,
Expand Down
24 changes: 24 additions & 0 deletions components/Layout/LayoutNavItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<template>
<ul>
<li class="inline-block py-2 text-xl font-semibold no-underline lg:text-base lg:px-4">
<NuxtLink :to="to">
<span class="text-xl text-white no-underline lg:text-black">
{{ label }}
</span>
</NuxtLink>
</li>
</ul>
</template>

<script setup>
const props = defineProps({
to: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
});
</script>
130 changes: 50 additions & 80 deletions components/Layout/LayoutNavbar.vue
Original file line number Diff line number Diff line change
@@ -1,92 +1,62 @@
<template>
<div>
<header
role="banner"
class="container flex flex-col justify-center px-0 pt-6 mx-auto mb-6"
>
<div class="flex flex-wrap lg:px-4">
<div class="w-9/12 pr-2 my-2 overflow-hidden lg:w-3/12 md:w-10/12">
<div class="ml-4 lg:ml-0">
<img
alt="Logo"
class="h-20 lg:h-24"
aria-label="Nettbutikk logo"
src="~/assets/svg/Logo.svg"
/>
</div>
<header
role="banner"
class="container flex flex-col justify-center px-0 pt-6 mx-auto mb-6"
>
<div class="flex flex-wrap lg:px-4">
<div class="w-9/12 pr-2 my-2 overflow-hidden lg:w-3/12 md:w-10/12">
<div class="ml-4 lg:ml-0">
<img
alt="Logo"
class="h-20 lg:h-24"
aria-label="Nettbutikk logo"
src="~/assets/svg/Logo.svg"
/>
</div>
<LayoutMobileMenu />
<div class="hidden lg:w-1/12 lg:block" />
<div
id="nav-content"
class="hidden w-full mt-4 bg-black lg:w-8/12 lg:block lg:bg-white lg:mt-0 lg:text-right"
>
<div class="px-6 lg:px-0 lg:pt-5 xl:pt-7">
<div>
<nav
id="block-main"
role="navigation"
aria-labelledby="block-main-menu"
</div>
<LayoutMobileMenu />
<div class="hidden lg:w-1/12 lg:block" />
<div
id="nav-content"
class="hidden w-full mt-4 bg-black lg:w-8/12 lg:block lg:bg-white lg:mt-0 lg:text-right"
>
<div class="px-6 lg:px-0 lg:pt-5 xl:pt-7">
<div>
<nav
id="block-main"
role="navigation"
aria-labelledby="block-main-menu"
>
<ul
class="items-center justify-end flex-1 pr-4 -mr-4 list-reset lg:flex"
>
<ul
class="items-center justify-end flex-1 pr-4 -mr-4 list-reset lg:flex"
<NavItem to="/" label="Home" />
<NavItem to="/products" label="Products" />
<NavItem to="/categories" label="Categories" />
<NavItem to="/search" label="Search" />
<li
class="inline-block py-2 text-xl font-semibold no-underline lg:text-base lg:px-4"
>
<li
class="inline-block py-2 text-xl font-semibold no-underline lg:text-base lg:px-4"
>
<NuxtLink to="/">
<span
class="text-xl text-white no-underline lg:text-black is-active"
>
Home
</span>
</NuxtLink>
</li>
<li
class="inline-block py-2 text-xl font-semibold no-underline lg:text-base lg:px-4"
>
<NuxtLink to="/products">
<span
class="text-xl text-white no-underline lg:text-black"
>Products</span
>
</NuxtLink>
</li>
<li
class="inline-block py-2 text-xl font-semibold no-underline lg:text-base lg:px-4"
>
<NuxtLink to="/categories">
<span
class="text-xl text-white no-underline lg:text-black is-active"
>Categories</span
>
</NuxtLink>
</li>
<li
class="inline-block py-2 text-xl font-semibold no-underline lg:text-base lg:px-4"
>
<NuxtLink to="/search">
<span
class="text-xl text-white no-underline lg:text-black is-active"
>Search</span
>
</NuxtLink>
</li>
<li
class="inline-block py-2 text-xl font-semibold no-underline lg:text-base lg:px-4"
>
<LayoutCart />
</li>
</ul>
</nav>
</div>
<LayoutCart />
</li>
</ul>
</nav>
</div>
</div>
</div>
</header>
</div>
</div>
</header>
</template>

<script setup>
/**
*
* Vue.js template for a header section of a web page.
*
*/
import NavItem from "@/components/Layout/LayoutNavItem.vue";
</script>

<style scoped>
header {
max-width: 1400px;
Expand Down
11 changes: 11 additions & 0 deletions components/Products/ProductImage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
</template>

<script setup>
/**
* Vue.js component for displaying an image with configurable properties.
*
* @param {Object} props - Object containing the component's properties.
* @param {String} props.alt - The alt text for the image (required).
* @param {String} props.src - The source URL for the image (required).
* @param {String} [props.width] - The width of the image.
* @param {String} [props.height] - The height of the image.
* @returns {Object} The Vue.js component object.
*/

import { computed } from "vue";

const props = defineProps({
Expand Down
8 changes: 8 additions & 0 deletions components/Products/ProductPrice.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
</template>

<script setup>
/**
* Displays the price of a product, with support for sale prices and variations.
*
* @param {Object} props - The component props.
* @param {Object} props.product - The product to display the price for.
* @param {string} [props.priceFontSize="normal"] - The font size for the price display.
* @param {boolean} [props.shouldCenterPrice=false] - Whether to center the price display.
*/
import { computed } from "vue";
import {
formatPrice,
Expand Down
112 changes: 47 additions & 65 deletions components/Products/ProductsShowAll.vue
Original file line number Diff line number Diff line change
@@ -1,72 +1,25 @@
<template>
<template v-if="allCategoryProducts?.productCategory?.products?.nodes">
<section>
<div id="product-container" class="flex flex-wrap items-center">
<template
v-for="product in allCategoryProducts.productCategory.products.nodes"
<div id="product-container" class="flex flex-wrap items-center">
<template v-for="product in products" :key="product.id">
<div class="flex flex-col mt-6 sm:w-1/2 md:w-1/3 lg:w-1/4 lg:mr-4">
<NuxtLink
class="text-black cursor-pointer hover:underline"
:to="productLink(product)"
>
<div
v-if="product.slug"
:key="product.id"
class="flex flex-col mt-6 sm:w1/2 md:w-1/3 lg:w-1/4 lg:mr-4"
>
<NuxtLink
class="text-black cursor-pointer hover:underline"
:to="{
path: '/product/' + product.slug,
query: { id: product.databaseId },
}"
>
<ProductImage :alt="product.name" :src="productImage(product)" />

<div class="flex justify-center pt-3">
<p class="text-2xl font-bold text-center cursor-pointer">
{{ product.name }}
</p>
</div>
</NuxtLink>
<ProductPrice
:product="product"
priceFontSize="normal"
:shouldCenterPrice="true"
/>
</div>
</template>
</div>
</section>
</template>
<div v-else>
<section>
<div id="product-container" class="flex flex-wrap items-center">
<template v-for="product in allProducts.products.nodes">
<div
v-if="product.slug"
:key="product.id"
class="flex flex-col mt-6 sm:w1/2 md:w-1/3 lg:w-1/4 lg:mr-4"
>
<NuxtLink
class="text-black cursor-pointer hover:underline"
:to="{
path: '/product/' + product.slug,
query: { id: product.databaseId },
}"
>
<ProductImage :alt="product.name" :src="productImage(product)" />
<div class="flex justify-center pt-3">
<p class="text-2xl font-bold text-center cursor-pointer">
{{ product.name }}
</p>
</div>
</NuxtLink>
<ProductPrice
:product="product"
priceFontSize="normal"
:shouldCenterPrice="true"
/>
<ProductImage :alt="product.name" :src="productImage(product)" />
<div class="flex justify-center pt-3">
<p class="text-2xl font-bold text-center cursor-pointer">
{{ product.name }}
</p>
</div>
</template>
</NuxtLink>
<ProductPrice
:product="product"
priceFontSize="normal"
:shouldCenterPrice="true"
/>
</div>
</section>
</template>
</div>
</template>

Expand All @@ -84,6 +37,35 @@ const props = defineProps({

const config = useRuntimeConfig();

const products = computed(() => {
return (
allCategoryProducts.value?.productCategory?.products?.nodes ||
allProducts.value?.products?.nodes ||
[]
);
});

/**
* Returns the path and query parameters for a product link.
*
* @param {Object} product - Object containing product information.
* @param {string} product.slug - The product's URL slug.
* @param {number} product.databaseId - The product's database ID.
* @return {Object} An object containing the product's path and query parameters.
*/
const productLink = (product) => {
return {
path: "/product/" + product.slug,
query: { id: product.databaseId },
};
};

/**
* Returns the source URL of a product image or a placeholder image if the product does not have an image.
*
* @param {Object} product - The product object containing the image source URL.
* @return {string} The source URL of the product image or a placeholder image if the product does not have an image.
*/
const productImage = (product) =>
product.image ? product.image.sourceUrl : config.public.placeholderImage;

Expand Down
4 changes: 2 additions & 2 deletions components/Products/ProductsSingleProduct.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ const { data } = await useAsyncQuery(GET_SINGLE_PRODUCT_QUERY, variables);
watch(
() => data.value,
(dataValue) => {
if (dataValue && dataValue.product.variations.nodes.length > 0) {
selectedVariation.value = dataValue.product.variations.nodes[0].databaseId;
if (dataValue && dataValue.product?.variations?.nodes?.length > 0) {
selectedVariation.value = dataValue.product?.variations?.nodes[0].databaseId;
}
},
{ immediate: true }
Expand Down
Loading