Skip to content

Commit

Permalink
feat: add unit as a new resource type (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
alcaprar authored Jul 21, 2024
1 parent 04e21c0 commit 76b0c85
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 1 deletion.
Binary file modified backend/.tmp/dev.data.db
Binary file not shown.
6 changes: 6 additions & 0 deletions backend/src/api/shop/content-types/shop/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@
"relation": "oneToMany",
"target": "api::sale.sale",
"mappedBy": "shop"
},
"units": {
"type": "relation",
"relation": "oneToMany",
"target": "api::unit.unit",
"mappedBy": "shop"
}
}
}
38 changes: 37 additions & 1 deletion backend/src/api/shop/controllers/shop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,41 @@ export default factories.createCoreController('api::shop.shop', {
strapi.log.info('saleEntities', saleEntities)

return saleEntities
}
},
async addUnit(ctx, next) {
const shop = ctx.params.shop;
let unitName = ctx.request.body.data.name || '';
strapi.log.info({ shop, unitName });

if (unitName == "") {
return ctx.badRequest('Unit is empty', { shop })
}

const unitEntity = await strapi.entityService.create('api::unit.unit', {
data: {
shop,
name: unitName
}
});

return unitEntity
},
async units(ctx, next) {
const shop = ctx.params.shop
strapi.log.info({ shop })

const shopEntity = await strapi.db.query('api::shop.shop').findOne({ where: { id: shop } })
strapi.log.info('shopEntity', shopEntity)

if (!shopEntity) {
return ctx.badRequest('Shop not found', { shop })
}

const unitEntities = await strapi.db
.query('api::unit.unit')
.findMany({ where: { shop } })
strapi.log.info('unitEntities', unitEntities)

return unitEntities
},
})
16 changes: 16 additions & 0 deletions backend/src/api/shop/routes/custom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ export default {
auth: false
}
},
{
method: 'GET',
path: '/shops/:shop/units',
handler: 'shop.units',
config: {
auth: false
}
},
{
method: 'POST',
path: '/shops/:shop/units',
handler: 'shop.addUnit',
config: {
auth: false
}
},
{
method: 'GET',
path: '/shops/:shopSlug/:clientUsername',
Expand Down
25 changes: 25 additions & 0 deletions backend/src/api/unit/content-types/unit/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"kind": "collectionType",
"collectionName": "units",
"info": {
"singularName": "unit",
"pluralName": "units",
"displayName": "Unit",
"description": ""
},
"options": {
"draftAndPublish": false
},
"pluginOptions": {},
"attributes": {
"name": {
"type": "string"
},
"shop": {
"type": "relation",
"relation": "manyToOne",
"target": "api::shop.shop",
"inversedBy": "units"
}
}
}
7 changes: 7 additions & 0 deletions backend/src/api/unit/controllers/unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* unit controller
*/

import { factories } from '@strapi/strapi'

export default factories.createCoreController('api::unit.unit');
7 changes: 7 additions & 0 deletions backend/src/api/unit/routes/unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* unit router
*/

import { factories } from '@strapi/strapi';

export default factories.createCoreRouter('api::unit.unit');
7 changes: 7 additions & 0 deletions backend/src/api/unit/services/unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* unit service
*/

import { factories } from '@strapi/strapi';

export default factories.createCoreService('api::unit.unit');
23 changes: 23 additions & 0 deletions backend/types/generated/contentTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -843,13 +843,35 @@ export interface ApiShopShop extends Schema.CollectionType {
owner: Attribute.Relation<'api::shop.shop', 'oneToOne', 'plugin::users-permissions.user'>
slug: Attribute.String & Attribute.Unique
sales: Attribute.Relation<'api::shop.shop', 'oneToMany', 'api::sale.sale'>
units: Attribute.Relation<'api::shop.shop', 'oneToMany', 'api::unit.unit'>
createdAt: Attribute.DateTime
updatedAt: Attribute.DateTime
createdBy: Attribute.Relation<'api::shop.shop', 'oneToOne', 'admin::user'> & Attribute.Private
updatedBy: Attribute.Relation<'api::shop.shop', 'oneToOne', 'admin::user'> & Attribute.Private
}
}

export interface ApiUnitUnit extends Schema.CollectionType {
collectionName: 'units'
info: {
singularName: 'unit'
pluralName: 'units'
displayName: 'Unit'
description: ''
}
options: {
draftAndPublish: false
}
attributes: {
name: Attribute.String
shop: Attribute.Relation<'api::unit.unit', 'manyToOne', 'api::shop.shop'>
createdAt: Attribute.DateTime
updatedAt: Attribute.DateTime
createdBy: Attribute.Relation<'api::unit.unit', 'oneToOne', 'admin::user'> & Attribute.Private
updatedBy: Attribute.Relation<'api::unit.unit', 'oneToOne', 'admin::user'> & Attribute.Private
}
}

declare module '@strapi/types' {
export module Shared {
export interface ContentTypes {
Expand All @@ -875,6 +897,7 @@ declare module '@strapi/types' {
'api::product-sale.product-sale': ApiProductSaleProductSale
'api::sale.sale': ApiSaleSale
'api::shop.shop': ApiShopShop
'api::unit.unit': ApiUnitUnit
}
}
}
4 changes: 4 additions & 0 deletions frontend/layouts/admin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ export default {
to: "/shop/clients",
icon: "bi-people-fill",
text: "Clienti"
}, {
to: "/shop/units",
icon: "bi-people-fill",
text: "Unità"
}, {
to: "/shop/changelog",
icon: "bi-journal-arrow-up",
Expand Down
95 changes: 95 additions & 0 deletions frontend/pages/shop/units/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<template>
<div
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Unità di misura <button type="button" class="btn btn-primary" data-bs-toggle="modal"
data-bs-target="#addUnit"><i class="bi-plus-circle-fill" /></button></h1>
</div>
<div class="table-responsive small">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>ID</th>
<th>Unità</th>
</tr>
</thead>
<tbody>
<tr v-for="unit in units" :key="unit.id">
<td> {{ unit.id }}</td>
<td> {{ unit.name }}</td>
</tr>
</tbody>
</table>
</div>
<div class="modal fade" id="addUnit" tabindex="-1" aria-labelledby="addUnitLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="addUnitLabel">Aggiungi unità</h1>
<button type="button" id="close-modal" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="col-12">
<label for="name" class="form-label">Nome</label>
<input type="text" id="name" class="form-control" required v-model="unit.name" />
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" @click="addUnit">Crea</button>
</div>
</div>
</div>
</div>
</template>

<script lang="ts">
export default {
setup() {
definePageMeta({ layout: "admin" });
},
data() {
return {
units: [] as Unit[],
unit: {
name: ""
}
};
},
async created() {
this.$loader.startLoader();
await this.refreshUnits();
this.$loader.stopLoader();
},
methods: {
async refreshUnits() {
let result = await this.$backend.units.getAll();
if (result.ok) {
this.units = result.val.map((item) => {
return {
id: item.id || -1,
name: item.name,
};
});
} else {
this.$toast.error("Errore nel recuperare la lista delle unità.")
}
},
async addUnit() {
this.$log().info("[pages][units][addUnit]");
let result = await this.$backend.units.create({
name: this.unit.name,
});
if (result.ok) {
this.$toast.info("Unità creato con successo.");
await this.refreshUnits();
document.getElementById('close-modal')?.click();
} else {
this.$toast.error("Errore nel creare la nuova unità.")
}
this.$loader.stopLoader();
}
}
};
</script>
64 changes: 64 additions & 0 deletions frontend/plugins/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { pino, type Logger } from "pino";
import { Ok, Err, Result } from 'ts-results';
import type { UnitDto } from "~/types/api";

export default defineNuxtPlugin((nuxtApp) => {
console.log('[plugins][api] $config:', nuxtApp.$config)
Expand All @@ -22,6 +23,7 @@ class ApiClient {
orders: OrdersClient
products: ProductsClient
sales: SalesClient
units: UnitsClient

constructor(
baseUrl: string,
Expand All @@ -31,6 +33,7 @@ class ApiClient {
this.orders = new OrdersClient(this.baseUrl)
this.products = new ProductsClient(this.baseUrl)
this.sales = new SalesClient(this.baseUrl)
this.units = new UnitsClient(this.baseUrl)
}

getBaseUrl(): string {
Expand Down Expand Up @@ -126,6 +129,67 @@ class ClientsClient {
}


class UnitsClient {
baseUrl: string

constructor(
baseUrl: string,
) {
this.baseUrl = baseUrl
}

async getAll(): Promise<Result<UnitDto[], ApiErrorVariant>> {
logger.debug("[ApiClient][Units][getAll]",);
const url = `${this.baseUrl}/shops/${SHOP_ID}/units`;
try {
let response = await fetch(url);
if (response.status == 404) {
logger.warn("[ApiClient][Units][getAll] not found")
return Err(ApiErrorVariant.NotFound)
}
let result: UnitDto[] = await response.json();
logger.debug("[ApiClient][Units][getAll] result", result);
return Ok(result)
} catch (error) {
logger.error("[ApiClient][Units][getAll] Error", error)
return Err(ApiErrorVariant.Generic)
}
}

async create(unit: UnitDto): Promise<Result<number, ApiErrorVariant>> {
logger.debug("[ApiClient][Units][create]", { unit })
const url = `${this.baseUrl}/shops/${SHOP_ID}/units`;
try {
let body = JSON.stringify({
data: {
name: unit.name,
},
});
logger.debug("[ApiClient][Units][create] body", body)
let response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body
});
if (response.status == 404) {
return Err(ApiErrorVariant.NotFound)
}
logger.debug("[ApiClient][Units][create] response", response)
let result = (await response.json());
logger.debug("[ApiClient][Units][create] result", result);
if (result.id != null) {
return Ok(result.id)
} else {
return Err(ApiErrorVariant.Generic)
}
} catch (error) {
logger.error("[ApiClient][Units][create] Error", error)
return Err(ApiErrorVariant.Generic)
}
}
}


class OrdersClient {
Expand Down
5 changes: 5 additions & 0 deletions frontend/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,8 @@ export interface ShopDto {
createdAt: string;
updatedAt: string;
}

export interface UnitDto {
id?: number,
name: string
}
4 changes: 4 additions & 0 deletions frontend/types/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export interface Product {
unit: UnitType;
}

export interface Unit {
id: number,
name: string
}
export enum UnitType {
Piece,
Kilogram,
Expand Down

0 comments on commit 76b0c85

Please sign in to comment.