-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #364 from vevcom/feat/shop
Feat/Shop
- Loading branch information
Showing
66 changed files
with
1,403 additions
and
46 deletions.
There are no files selected for viewing
Submodule docs
updated
from 97b8ef to 3cc94e
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
'use server' | ||
|
||
import { action } from '@/actions/action' | ||
import { createProduct, createProductForShop, createShopProductConnection } from '@/services/shop/product/create' | ||
import { readProduct, readProducts } from '@/services/shop/product/read' | ||
import { updateProduct, updateProductForShop } from '@/services/shop/product/update' | ||
import { createShop } from '@/services/shop/shop/create' | ||
import { readShop, readShops } from '@/services/shop/shop/read' | ||
|
||
export const readShopsAction = action(readShops) | ||
export const readShopAction = action(readShop) | ||
export const createShopAction = action(createShop) | ||
|
||
export const readProductsAction = action(readProducts) | ||
export const readProductAction = action(readProduct) | ||
export const createProductAction = action(createProduct) | ||
export const updateProductAction = action(updateProduct) | ||
|
||
export const createProductForShopAction = action(createProductForShop) | ||
export const updateProductForShopAction = action(updateProductForShop) | ||
|
||
export const createShopProductConnectionAction = action(createShopProductConnection) |
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
@use '@/styles/ohma'; | ||
|
||
.table { | ||
@include ohma.table(); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import styles from './page.module.scss' | ||
import ProductForm from '@/app/admin/product/productForm' | ||
import { readProductAction } from '@/actions/shop' | ||
import { unwrapActionReturn } from '@/app/redirectToErrorPage' | ||
import PageWrapper from '@/app/_components/PageWrapper/PageWrapper' | ||
import { v4 as uuid } from 'uuid' | ||
import Link from 'next/link' | ||
import { displayPrice } from '@/lib/money/convert' | ||
|
||
export default async function ProductPage({ | ||
params | ||
}: { | ||
params: { | ||
productId: number | ||
} | ||
}) { | ||
const product = unwrapActionReturn(await readProductAction({ productId: Number(params.productId) })) | ||
|
||
return <PageWrapper | ||
title={product.name} | ||
> | ||
<ProductForm product={product} /> | ||
|
||
<table className={styles.table}> | ||
<thead> | ||
<tr> | ||
<th>Navn</th> | ||
<th>Aktiv</th> | ||
<th>Pris</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{product.ShopProduct.map(shopProduct => <tr key={uuid()}> | ||
<td><Link href={`/admin/shop/${shopProduct.shopId}`}>{shopProduct.shop.name}</Link></td> | ||
<td>{shopProduct.active ? 'AKTIV' : 'INAKTIV'}</td> | ||
<td>{displayPrice(shopProduct.price, false)}</td> | ||
</tr>)} | ||
</tbody> | ||
</table> | ||
</PageWrapper> | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
@use '@/styles/ohma'; | ||
|
||
.table { | ||
@include ohma.table(); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
'use server' | ||
|
||
import ProductForm from './productForm' | ||
import styles from './page.module.scss' | ||
import { readProductsAction } from '@/actions/shop' | ||
import { AddHeaderItemPopUp } from '@/app/_components/HeaderItems/HeaderItemPopUp' | ||
import PageWrapper from '@/app/_components/PageWrapper/PageWrapper' | ||
import { unwrapActionReturn } from '@/app/redirectToErrorPage' | ||
import { sortObjectsByName } from '@/lib/sortObjects' | ||
import { v4 as uuid } from 'uuid' | ||
import Link from 'next/link' | ||
|
||
|
||
export default async function ProductPage() { | ||
const products = unwrapActionReturn(await readProductsAction()) | ||
|
||
return <PageWrapper | ||
title="Produkter" | ||
headerItem={ | ||
<AddHeaderItemPopUp PopUpKey="ProductForm"> | ||
<ProductForm /> | ||
</AddHeaderItemPopUp> | ||
} | ||
> | ||
<table className={styles.table}> | ||
<thead> | ||
<tr> | ||
<th>Produkt</th> | ||
<th>Beskrivelse</th> | ||
<th>Strekkode</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{sortObjectsByName(products).map(product => <tr key={uuid()}> | ||
<Link style={{ display: 'contents' }} href={`./product/${product.id}`} passHref> | ||
<td>{product.name}</td> | ||
<td>{product.description}</td> | ||
<td>{product.barcode ?? ''}</td> | ||
</Link> | ||
</tr>)} | ||
</tbody> | ||
</table> | ||
</PageWrapper> | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { createProductAction, updateProductAction } from '@/actions/shop' | ||
import Form from '@/app/_components/Form/Form' | ||
import TextInput from '@/app/_components/UI/TextInput' | ||
import type { Product } from '@prisma/client' | ||
|
||
|
||
export default function ProductForm({ | ||
product | ||
}: { | ||
product?: Product | ||
}) { | ||
const submitForm = product | ||
? updateProductAction | ||
: createProductAction | ||
return <Form | ||
action={submitForm} | ||
submitText={product ? 'Oppdater produkt' : 'Lag nytt produkt'} | ||
refreshOnSuccess | ||
> | ||
<TextInput name="name" label="Navn" defaultValue={product?.name} /> | ||
<TextInput name="description" label="Beskrivelse" defaultValue={product?.description} /> | ||
<TextInput name="barcode" label="Strekkode" defaultValue={product?.barcode ? product.barcode : ''} /> | ||
{product && <input type="hidden" name="productId" value={product.id} /> } | ||
</Form> | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { createProductForShopAction, updateProductForShopAction } from '@/actions/shop' | ||
import Form from '@/app/_components/Form/Form' | ||
import Checkbox from '@/app/_components/UI/Checkbox' | ||
import NumberInput from '@/app/_components/UI/NumberInput' | ||
import TextInput from '@/app/_components/UI/TextInput' | ||
import { displayPrice } from '@/lib/money/convert' | ||
import type { ExtendedProduct } from '@/services/shop/product/Types' | ||
|
||
|
||
export function EditProductForShopForm({ | ||
shopId, | ||
product, | ||
}: { | ||
shopId: number, | ||
product?: ExtendedProduct, | ||
}) { | ||
const submitAction = product | ||
? updateProductForShopAction.bind(null, { shopId, productId: product.id }) | ||
: createProductForShopAction.bind(null, { shopId }) | ||
|
||
return <Form | ||
action={submitAction} | ||
submitText={product ? 'Oppdater produkt' : 'Lag nytt produkt'} | ||
> | ||
<TextInput name="name" label="Navn" defaultValue={product?.name}/> | ||
<TextInput name="description" label="Beskrivelse" defaultValue={product?.description}/> | ||
<TextInput name="barcode" label="Strekkode" defaultValue={product?.barcode ?? ''}/> | ||
{product && <> | ||
<input type="hidden" name="productId" value={product.id} /> | ||
<Checkbox name="active" label="Aktiv" defaultChecked={product?.active} /> | ||
</>} | ||
<NumberInput name="price" label="Pris" defaultValue={product ? displayPrice(product.price, true) : undefined}/> | ||
</Form> | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
'use client' | ||
import { createShopProductConnectionAction } from '@/actions/shop' | ||
import Form from '@/app/_components/Form/Form' | ||
import NumberInput from '@/app/_components/UI/NumberInput' | ||
import { SelectNumber } from '@/app/_components/UI/Select' | ||
import type { Product } from '@prisma/client' | ||
|
||
|
||
export default function FindProductForm({ | ||
shopId, | ||
products, | ||
}: { | ||
shopId: number, | ||
products: Pick<Product, 'id' | 'name'>[] | ||
}) { | ||
if (products.length === 0) return <></> | ||
|
||
return <Form | ||
action={createShopProductConnectionAction} | ||
submitText="Legg til produkt" | ||
> | ||
<SelectNumber name="productId" label="Produkt" options={products.map(product => ({ | ||
label: product.name, | ||
value: product.id, | ||
}))} /> | ||
<input type="hidden" name="shopId" value={shopId} /> | ||
<NumberInput name="price" label="Pris" /> | ||
</Form> | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
@use '@/styles/ohma'; | ||
|
||
.button { | ||
@include ohma.btn(ohma.$colors-primary); | ||
} | ||
|
||
.table { | ||
@include ohma.table(); | ||
} | ||
|
||
.deactivatedProduct { | ||
color: ohma.$colors-gray-600; | ||
font-style: italic; | ||
} | ||
|
||
.editButtonWrapper { | ||
text-align: center; | ||
|
||
> button { | ||
width: 30px; | ||
height: 30px; | ||
border: none; | ||
background: transparent; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { EditProductForShopForm } from './EditProductForShopForm' | ||
import styles from './page.module.scss' | ||
import FindProductForm from './FindProductForm' | ||
import { readProductsAction, readShopAction } from '@/actions/shop' | ||
import PageWrapper from '@/app/_components/PageWrapper/PageWrapper' | ||
import PopUp from '@/app/_components/PopUp/PopUp' | ||
import { unwrapActionReturn } from '@/app/redirectToErrorPage' | ||
import { displayPrice } from '@/lib/money/convert' | ||
import { sortObjectsByName } from '@/lib/sortObjects' | ||
import { faPencil } from '@fortawesome/free-solid-svg-icons' | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||
import { notFound } from 'next/navigation' | ||
import { v4 as uuid } from 'uuid' | ||
import type { Product } from '@prisma/client' | ||
|
||
export default async function Shop(params: { | ||
params: { | ||
shop: string | ||
} | ||
}) { | ||
const shopId = parseInt(params.params.shop, 10) | ||
if (isNaN(shopId)) notFound() | ||
|
||
const shopData = unwrapActionReturn(await readShopAction({ | ||
shopId, | ||
})) | ||
|
||
if (!shopData) notFound() | ||
|
||
const allProducts = unwrapActionReturn(await readProductsAction()) | ||
let unconnectedProducts: Product[] = [] | ||
if (allProducts) { | ||
const existingProductIds = new Set(shopData.products.map(p => p.id)) | ||
unconnectedProducts = allProducts.filter(product => !existingProductIds.has(product.id)) | ||
} | ||
|
||
return <PageWrapper | ||
title={shopData.name} | ||
> | ||
<p>{shopData.description}</p> | ||
|
||
<PopUp | ||
showButtonClass={styles.button} | ||
showButtonContent="Legg til Produkt" | ||
PopUpKey="createProductForShop" | ||
> | ||
<FindProductForm shopId={shopId} products={unconnectedProducts} /> | ||
<br /> | ||
<EditProductForShopForm shopId={shopId} /> | ||
</PopUp> | ||
|
||
<table className={styles.table}> | ||
<thead> | ||
<tr> | ||
<th>Rediger</th> | ||
<th>Produkt</th> | ||
<th>Beskrivelse</th> | ||
<th>Pris</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{sortObjectsByName(shopData.products).map(product => <tr | ||
key={uuid()} | ||
className={product.active ? '' : styles.deactivatedProduct} | ||
> | ||
<td className={styles.editButtonWrapper}> | ||
<PopUp | ||
showButtonContent={<FontAwesomeIcon icon={faPencil} />} | ||
PopUpKey={'EditProductForShop'} | ||
> | ||
<EditProductForShopForm shopId={shopId} product={product} /> | ||
</PopUp> | ||
</td> | ||
<td>{product.name}</td> | ||
<td>{product.description}</td> | ||
<td>{displayPrice(product.price, false)}</td> | ||
</tr>)} | ||
</tbody> | ||
</table> | ||
</PageWrapper> | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
@use '@/styles/ohma'; | ||
|
||
.table { | ||
@include ohma.table(); | ||
} |
Oops, something went wrong.