diff --git a/backend/app/src/main/java/eu/viandeendirect/domains/order/OrderService.java b/backend/app/src/main/java/eu/viandeendirect/domains/order/OrderService.java index 7c7e9fd..32bd8a5 100644 --- a/backend/app/src/main/java/eu/viandeendirect/domains/order/OrderService.java +++ b/backend/app/src/main/java/eu/viandeendirect/domains/order/OrderService.java @@ -150,7 +150,6 @@ private void updateQuantitiesSold(Order order) { public void processOrderPaymentCompletion(Order order) { order.setStatus(OrderStatus.PAYMENT_COMPLETED); - // TODO: trigger an email to the customer notifyProducers(order); notifyCustomer(order); orderRepository.save(order); diff --git a/frontend/app/src/api/mock/MockApi.ts b/frontend/app/src/api/mock/MockApi.ts index c5f6f24..a209d35 100644 --- a/frontend/app/src/api/mock/MockApi.ts +++ b/frontend/app/src/api/mock/MockApi.ts @@ -12,70 +12,95 @@ export class MockApi { mockApiSales: MockApiSales = new MockApiSales() mockApiProducers: MockApiProducers = new MockApiProducers() - createBeefProduction() { + private log(methodName: String, args: any) { + console.log(`MockApi.${methodName} has been invoked with following artguments : ${JSON.stringify(args)}`) } - getProductions() { + createBeefProduction(args) { + this.log('createBeefProduction', args) + } + + getProductions(args) { + this.log('getProductions', args) return this.mockApiProductions.getProductions() } - getProductionPercentageSold() { + getProductionPercentageSold(args) { + this.log('getProductionPercentageSold', args) return this.mockApiProductions.getProductionPercentageSold() } - getBeefProduction() { + getBeefProduction(args) { + this.log('getBeefProduction', args) return this.mockApiProductions.getBeefProduction() } - getPackageTemplates() { + getPackageTemplates(args) { + this.log('getPackageTemplates', args) return this.mockApiProductions.getPackageTemplates() } - getAddresses() { + getAddresses(args) { + this.log('getAddresses', args) return this.mockApiAddresses.getAddresses() } - createCustomer(customer){ - return this.mockApiCustomers.createCustomer(customer) + createCustomer(args){ + this.log('createCustomer', args) + return this.mockApiCustomers.createCustomer(args) } - getCustomer(){ + getCustomer(args){ + this.log('getCustomer', args) return this.mockApiCustomers.getCustomer() } - getProducerSales() { + createProducerSale(args) { + this.log('createProducerSale', args) + } + + getProducerSales(args) { + this.log('getProducerSales', args) return this.mockApiProducers.getProducerSales() } - getProducerCustomers() { + getProducerCustomers(args) { + this.log('getProducerCustomers', args) return this.mockApiProducers.getCustomers() } - getSales() { + getSales(args) { + this.log('getSales', args) return this.mockApiSales.getSales() } - getSale() { + getSale(args) { + this.log('getSale', args) return this.mockApiSales.getSale() } - getSaleOrders() { + getSaleOrders(args) { + this.log('getSaleOrders', args) return this.mockApiSales.getSaleOrders() } - getSaleProductions() { + getSaleProductions(args) { + this.log('getSaleProductions', args) return this.mockApiSales.getSaleProductions() } - getOrder() { + getOrder(args) { + this.log('getOrder', args) return this.mockApiSales.getOrder() } - createOrder(order) { - return this.mockApiSales.createOrder(order) + createOrder(args) { + this.log('createOrder', args) + return this.mockApiSales.createOrder(args) } - getProducer() { + getProducer(args) { + this.log('getProducer', args) return this.mockApiProducers.getProducer() } } \ No newline at end of file diff --git a/frontend/app/src/api/mock/MockApiCustomers.ts b/frontend/app/src/api/mock/MockApiCustomers.ts index 9770426..5fd731c 100644 --- a/frontend/app/src/api/mock/MockApiCustomers.ts +++ b/frontend/app/src/api/mock/MockApiCustomers.ts @@ -12,7 +12,6 @@ export class MockApiCustomers { email: 'bob.marcel@email.eu' } } - //return undefined } createCustomer(customer: Customer): Customer { diff --git a/frontend/app/src/domains/production/components/ProductionCard.tsx b/frontend/app/src/domains/production/components/ProductionCard.tsx index 8b8d437..8e5940f 100644 --- a/frontend/app/src/domains/production/components/ProductionCard.tsx +++ b/frontend/app/src/domains/production/components/ProductionCard.tsx @@ -4,7 +4,7 @@ import BeefProductionCard from "./BeefProductionCard.tsx" export default function ProductionCard({ production: production, showActions: showActions, - clickCallback: clickCallback + onClick: onClick }) { switch (production.productionType) { @@ -13,7 +13,7 @@ export default function ProductionCard({ key={production.id} production={production} showActions={showActions} - clickCallback={clickCallback}> + onClick={onClick}> default : return <> diff --git a/frontend/app/src/domains/sale/components/SaleProductionSelector.js b/frontend/app/src/domains/sale/components/SaleProductionSelector.js index 0f2e9ea..f3c276b 100644 --- a/frontend/app/src/domains/sale/components/SaleProductionSelector.js +++ b/frontend/app/src/domains/sale/components/SaleProductionSelector.js @@ -1,38 +1,13 @@ -import { useState, useEffect } from 'react' -import { useKeycloak } from '@react-keycloak/web' -import { ApiBuilder } from '../../../api/ApiBuilder.ts' import ProductionCard from '../../production/components/ProductionCard.tsx' -export default function SaleProductionSelector({selectProduction: selectProduction}) { +export default function SaleProductionSelector({selectProduction: selectProduction, productions: productions}) { - const { keycloak, initialized } = useKeycloak() - const [productionsForSale, setProductionsForSale] = useState([]) - const apiBuilder = new ApiBuilder() - - useEffect(() => { - loadProductionsForSale() - }, [keycloak]) - - function loadProductionsForSale() { - apiBuilder.getAuthenticatedApi(keycloak).then(api => { - apiBuilder.invokeAuthenticatedApi(() => { - api.getProductions({ 'forSale': true }, (error, data, response) => { - if (error) { - console.error(error) - } else { - console.log('api.getProductions called successfully. Returned data: ' + data) - setProductionsForSale(data) - } - }) - }, keycloak) - }) - } function handleProductSelection(production) { selectProduction(production) } - return productionsForSale.map(production => { + return productions.map(production => { return
{ - loadOrder() - }, [keycloak]) - - function loadOrder() { - apiBuilder.getAuthenticatedApi(keycloak).then(api => { - apiBuilder.invokeAuthenticatedApi(() => { - api.getOrder(rawOrder.id, (error, data, response) => { - if (error) { - console.error(error) - } else { - console.log('api.getOrder called successfully. Returned data: ' + data) - setOrder(data) - } - }) - }, keycloak) - }) - } + const navigate = useNavigate() + const order: Order = useLoaderData() return <> Détails de la commande - + +} + +export async function loadOrderViewData(orderId: number, keycloakClient): Promise { + const apiBuilder = new ApiBuilder() + const api = await apiBuilder.getAuthenticatedApi(keycloakClient) + return await api.getOrder({orderId}) } \ No newline at end of file diff --git a/frontend/app/src/domains/sale/views/ProducerOrderForm.tsx b/frontend/app/src/domains/sale/views/ProducerOrderForm.tsx index 72a4486..4ff7600 100644 --- a/frontend/app/src/domains/sale/views/ProducerOrderForm.tsx +++ b/frontend/app/src/domains/sale/views/ProducerOrderForm.tsx @@ -7,78 +7,54 @@ import dayjs from 'dayjs' import { useKeycloak } from '@react-keycloak/web' import { ApiBuilder } from '../../../api/ApiBuilder.ts' -import Customer from "@viandeendirect/api/dist/models/Customer" -import OrderItem from "@viandeendirect/api/dist/models/OrderItem" -import Order from "@viandeendirect/api/dist/models/Order" -import Production from "@viandeendirect/api/dist/models/Production" -import PackageLot from "@viandeendirect/api/dist/models/PackageLot" -import Sale from "@viandeendirect/api/dist/models/Sale" +import { Customer } from "@viandeendirect/api/dist/models/Customer" +import { OrderItem } from "@viandeendirect/api/dist/models/OrderItem" +import {Order} from "@viandeendirect/api/dist/models/Order" +import { Production } from "@viandeendirect/api/dist/models/Production" +import { PackageLot } from "@viandeendirect/api/dist/models/PackageLot" +import { Sale } from "@viandeendirect/api/dist/models/Sale" import PackageSelector from '../components/PackageSelector.tsx' import CustomerSelector from '../components/CustomerSelector.tsx' import OrderSummary from '../components/OrderSummary.tsx' -import { ApiInvoker } from '../../../api/ApiInvoker.ts' +import { ProducerService } from '../../commons/service/ProducerService.ts' +import { useLoaderData, useNavigate } from 'react-router-dom' -export default function ProducerOrderForm({ producer: producer, sale: sale, returnCallback: returnCallback }) { +// TODO : corriger erreur eu retour de la création si saisie d'un nouvel utilisateur +export default function ProducerOrderForm() { const SET_ITEMS_STEP = 1 const SET_CUSTOMER_STEP = 2 const CONFIRMATION_STEP = 3 - const { keycloak, initialized } = useKeycloak() - const apiInvoker = new ApiInvoker() - const apiBuilder = new ApiBuilder() + const { keycloak } = useKeycloak() + const navigate = useNavigate() + const data: ProducerOrderFormData = useLoaderData() + const productions = data.productions + const customers = data.customers + const sale = data.sale - const [productions, setProductions] = useState>([]) - const [customers, setCustomers] = useState>([]) - const [order, setOrder] = useState({sale: sale}) + const [order, setOrder] = useState({sale: sale, customer: {}}) const [items, setItems] = useState>([]) const [activeStep, setActiveStep] = useState(SET_ITEMS_STEP) - useEffect(() => { - loadProductions() - loadCustomers() - }, [keycloak]) - - function loadProductions() { - apiInvoker.callApiAuthenticatedly( - keycloak, - api => api.getSaleProductions, - sale.id, - setProductions, - console.error) - } - - function loadCustomers() { - apiInvoker.callApiAuthenticatedly( - keycloak, - api => api.getProducerCustomers, - producer.id, - setCustomers, - console.error) + async function createCustomerAndOrder(customer: Customer){ + const apiBuilder = new ApiBuilder() + const api = await apiBuilder.getAuthenticatedApi(keycloak) + const createdCustomer = await api.createCustomer({customer: customer}) + const updatedOrder = {...order, customer: createdCustomer} + setOrder(updatedOrder) + await api.createOrder({order: updatedOrder}) + navigate(-1) } - function createCustomerAndOrder(customer: Customer){ - apiInvoker.callApiAuthenticatedly( - keycloak, - api => api.createCustomer, - customer, - customer => { - const updatedOrder = {...order, customer: customer} - setOrder(updatedOrder) - createOrder(updatedOrder) - }, - console.error) + async function createOrder(){ + const apiBuilder = new ApiBuilder() + const api = await apiBuilder.getAuthenticatedApi(keycloak) + await api.createOrder({order: order}) + navigate(-1) } - function createOrder(order: Order) { - apiInvoker.callApiAuthenticatedly( - keycloak, - api => api.createOrder, - order, - () => returnCallback(sale), - console.error) - } return <> Creation d'une commande pour la vente du {dayjs(sale.deliveryStart).format('DD/MM/YYYY')} - {sale.deliveryAddressName} @@ -114,7 +90,7 @@ export default function ProducerOrderForm({ producer: producer, sale: sale, retu - + function packageLots() { @@ -147,7 +123,24 @@ export default function ProducerOrderForm({ producer: producer, sale: sale, retu if(!order.customer.id) { createCustomerAndOrder(order.customer) } else { - createOrder(order) + createOrder() } } } + +class ProducerOrderFormData { + productions: Array + customers: Array + sale: Sale +} + +export async function loadProducerOrderFormData(saleId: number, keycloakClient): Promise { + const producerService = new ProducerService(keycloakClient) + const producer = await producerService.asyncLoadProducer() + const apiBuilder = new ApiBuilder() + const api = await apiBuilder.getAuthenticatedApi(keycloakClient) + const productions = await api.getSaleProductions({saleId: saleId}) + const customers = await api.getProducerCustomers({producerId: producer.id}) + const sale = await api.getSale({saleId: saleId}) + return {productions: productions, customers: customers, sale: sale} +} diff --git a/frontend/app/src/domains/sale/views/SaleForm.tsx b/frontend/app/src/domains/sale/views/SaleForm.tsx index 7c92bfc..d128daa 100644 --- a/frontend/app/src/domains/sale/views/SaleForm.tsx +++ b/frontend/app/src/domains/sale/views/SaleForm.tsx @@ -1,52 +1,42 @@ import React from 'react' -import { useState, useEffect } from 'react' +import { useState } from 'react' +import { useLoaderData, useNavigate } from 'react-router-dom' import { useKeycloak } from '@react-keycloak/web' import { Button, ButtonGroup, Stepper, Step, StepLabel, StepContent, Typography, Autocomplete } from "@mui/material" import { ApiBuilder } from '../../../api/ApiBuilder.ts' import { DatePickerElement, TextFieldElement, FormContainer, TimePickerElement } from 'react-hook-form-mui' - -import Sale from '@viandeendirect/api/dist/models/Sale' - -import SaleProductionSelector from '../components/SaleProductionSelector.js' import 'dayjs/locale/fr'; import dayjs from 'dayjs' -import { useNavigate } from 'react-router-dom' -const steps = ['Choisir une production', 'Définir le lieu et l\'heure', 'Choisir les produits mis en vente'] +import SaleProductionSelector from '../components/SaleProductionSelector.js' +import { Sale } from '@viandeendirect/api/dist/models/Sale' +import { Address } from '@viandeendirect/api/dist/models/Address' +import { Production } from '@viandeendirect/api/dist/models/Production' +import { Producer } from '@viandeendirect/api/dist/models/Producer' +import { ProducerService } from '../../commons/service/ProducerService.ts' /** * @param {Production} production * @returns */ -export default function SaleForm({producer: producer}) { +export default function SaleForm() { const SELECT_PRODUCTION_STEP = 'SELECT_PRODUCTION_STEP' const SET_DELIVERY_DATE_STEP = 'SET_DELIVERY_DATE_STEP' const SET_DELIVERY_ADDRESS_STEP = 'SET_DELIVERY_ADDRESS_STEP' const CONFIRMATION_STEP = 'CONFIRMATION_STEP' - const { keycloak, initialized } = useKeycloak() + const { keycloak } = useKeycloak() const navigate = useNavigate() + const data: SaleFormData = useLoaderData() + const addresses: Array
= data.addresses + const productions: Array = data.productions + const producer: Producer = data.producer + + const [activeStep, setActiveStep] = useState(SELECT_PRODUCTION_STEP) const [sale, setSale] = useState({}) - const [addresses, setAddresses] = useState([]) const [selectedAddress, setSelectedAddress] = useState(undefined) - const apiBuilder = new ApiBuilder() - - useEffect(() => { - apiBuilder.getAuthenticatedApi(keycloak).then(api => { - apiBuilder.invokeAuthenticatedApi(() => { - api.getAddresses((error, data, response) => { - if (error) { - console.error(error); - } else { - console.log('api.getAddresses called successfully. Returned data: ' + data); - setAddresses(data) - } - }) - }, keycloak) - }) - }, [keycloak]) return <> Nouvelle vente @@ -55,7 +45,7 @@ export default function SaleForm({producer: producer}) { Choisir une production
- +
@@ -189,19 +179,16 @@ export default function SaleForm({producer: producer}) { setActiveStep(CONFIRMATION_STEP) } - function validate() { - apiBuilder.getAuthenticatedApi(keycloak).then(api => { - apiBuilder.invokeAuthenticatedApi(() => { - api.createProducerSale(producer.id, sale, (error, data, response) => { - if (error) { - console.error(error) - } else { - console.log('API called successfully. Returned data: ' + data) - navigate(-1) - } - }) - }, keycloak) - }); + async function validate() { + const apiBuilder = new ApiBuilder() + const api = await apiBuilder.getAuthenticatedApi(keycloak) + try { + await api.createProducerSale({producerId: +producer.id, sale: sale}) + console.log('API called successfully. Returned data: ' + data) + navigate(-1) + } catch (error) { + console.error(error) + } } function cancel() { @@ -209,6 +196,18 @@ export default function SaleForm({producer: producer}) { } } -export async function loadSaleFormData(keycloakClient) { - //TODO : à implémenter +class SaleFormData { + addresses: Array
+ productions: Array + producer: Producer +} + +export async function loadSaleFormData(keycloakClient): Promise { + const producerService = new ProducerService(keycloakClient) + const producer: Producer = await producerService.asyncLoadProducer() + const apiBuilder = new ApiBuilder() + const api = await apiBuilder.getAuthenticatedApi(keycloakClient) + const addresses: Array
= await api.getAddresses() + const productions: Array = await api.getProductions({forSale: true}) + return {addresses: addresses, productions: productions, producer: producer} } \ No newline at end of file diff --git a/frontend/app/src/domains/sale/views/SalesList.tsx b/frontend/app/src/domains/sale/views/SalesList.tsx index a099308..1d8629d 100644 --- a/frontend/app/src/domains/sale/views/SalesList.tsx +++ b/frontend/app/src/domains/sale/views/SalesList.tsx @@ -9,8 +9,6 @@ import { ProducerService } from '../../commons/service/ProducerService.ts' import { ApiBuilder } from '../../../api/ApiBuilder.ts'; import { Sale } from '@viandeendirect/api/dist/models/Sale'; -//TODO : finir la conversion - export default function SalesList() { const navigate = useNavigate() diff --git a/frontend/app/src/layouts/producer/ProducerRouterFactory.tsx b/frontend/app/src/layouts/producer/ProducerRouterFactory.tsx index bc72c07..a216890 100644 --- a/frontend/app/src/layouts/producer/ProducerRouterFactory.tsx +++ b/frontend/app/src/layouts/producer/ProducerRouterFactory.tsx @@ -11,10 +11,10 @@ import BeefProductionView from "../../domains/production/views/beefProduction/Be import BeefProductionCreator, { loadBeefProductionCreatorData } from "../../domains/production/views/beefProduction/BeefProductionCreator.tsx"; import ProductionsList, { loadProductionListData } from "../../domains/production/views/ProductionsList.tsx"; import SalesList, { loadSalesListData } from "../../domains/sale/views/SalesList.tsx"; -import SaleForm from "../../domains/sale/views/SaleForm.tsx"; +import SaleForm, { loadSaleFormData } from "../../domains/sale/views/SaleForm.tsx"; import OrdersList, { loadOrdersListData } from "../../domains/sale/views/OrdersList.tsx"; -import OrderView from "../../domains/sale/views/OrderView.tsx"; -import ProducerOrderForm from "../../domains/sale/views/ProducerOrderForm.tsx"; +import OrderView, { loadOrderViewData } from "../../domains/sale/views/OrderView.tsx"; +import ProducerOrderForm, { loadProducerOrderFormData } from "../../domains/sale/views/ProducerOrderForm.tsx"; export class ProducerRouterFactory { getRouter(keycloakClient) { @@ -52,7 +52,8 @@ export class ProducerRouterFactory { }, { path: '/sales/creation', - element: + element: , + loader: async () => loadSaleFormData(keycloakClient) }, { path: '/sale/:saleId/orders', @@ -61,11 +62,13 @@ export class ProducerRouterFactory { }, { path: '/sale/:saleId/order/:orderId', - element: + element: , + loader: async ({params}) => loadOrderViewData(+params.orderId, keycloakClient) }, { path: '/sale/:saleId/order/creation', - element: + element: , + loader: async ({params}) => loadProducerOrderFormData(+params.saleId, keycloakClient) }, { path: '/customers',