Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/153/handle article resa #162

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
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
28 changes: 25 additions & 3 deletions backend/src/resolvers/ArticleResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ class NewArticleInput {
class ArticleResolver {
@Query(() => [Article])
async getAllArticles() {
const article = await Article.find({ relations: { product: true, reservations: true }, order: { product: {name: "ASC" }}
})
return article
const article = await Article.find({
relations: { product: true, reservations: true },
order: { product: { name: "ASC" } },
});
return article;
}

@Authorized(Role.Admin)
Expand Down Expand Up @@ -76,6 +78,26 @@ class ArticleResolver {

return article;
}

@Mutation(() => String)
async canDeleteArticle(
@Arg("articleId") articleId: string
): Promise<boolean> {
const article = await Article.findOne({
where: { id: Number.parseInt(articleId) },
relations: { reservations: true },
});

if (!article) {
throw new Error("Article not found");
}

if (article.reservations && article.reservations.length > 0) {
throw new Error("Article is part of a reservation and cannot be deleted");
}

return true;
}
}

export default ArticleResolver;
32 changes: 26 additions & 6 deletions frontend/src/components/DeleteArticleButton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useMutation } from "@apollo/client";
import {
GetAllArticlesDocument,
useDeleteArticleMutation,
} from "../generated/graphql-types";
import { CAN_DELETE_ARTICLE } from "../graphql/mutations";

import { Button, message, Popconfirm } from "antd";

function DeleteProductButton({ articleId }: { articleId: string }) {
Expand All @@ -10,20 +13,37 @@ function DeleteProductButton({ articleId }: { articleId: string }) {
message.success("article supprimé avec succès");
},
});
const [canDeleteArticle] = useMutation(CAN_DELETE_ARTICLE);

const handleDelete = async () => {
try {
const { data } = await canDeleteArticle({
variables: { articleId: articleId.toString() },
});

if (data?.canDeleteArticle) {
await deleteArticle({
variables: { deleteArticleId: articleId.toString() },
refetchQueries: [GetAllArticlesDocument],
});
} else {
message.error(
"L'article fait partie d'une réservation et ne peut pas être supprimé."
);
}
} catch (error) {
console.error("Erreur lors de la suppression de l'article", error);
}
};
return (
<Popconfirm
title="Supprimer cet article ? "
description="Toutes les données le concernant seront perdues."
okText="Oui"
className="bg-red-500 text-white hover:bg-red-600 focus:outline-none"
cancelText="Non"
onConfirm={() =>
deleteArticle({
variables: { deleteArticleId: articleId },
refetchQueries: [GetAllArticlesDocument],
})
}
onConfirm={handleDelete}

>
<Button>Supprimer</Button>
</Popconfirm>
Expand Down
100 changes: 99 additions & 1 deletion frontend/src/generated/graphql-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export type Article = {

export type Mutation = {
__typename?: 'Mutation';
canDeleteArticle: Scalars['String']['output'];
cancelReservation: Reservation;
createNewArticle: Article;
createNewProduct: Product;
Expand All @@ -40,6 +41,11 @@ export type Mutation = {
};


export type MutationCanDeleteArticleArgs = {
articleId: Scalars['String']['input'];
};


export type MutationCancelReservationArgs = {
reservationId: Scalars['ID']['input'];
};
Expand Down Expand Up @@ -286,6 +292,13 @@ export type HandleReservationMutationVariables = Exact<{

export type HandleReservationMutation = { __typename?: 'Mutation', handleReservation: { __typename?: 'Reservation', id: string } };

export type CanDeleteArticleMutationVariables = Exact<{
articleId: Scalars['String']['input'];
}>;


export type CanDeleteArticleMutation = { __typename?: 'Mutation', canDeleteArticle: string };

export type GetAllProductsQueryVariables = Exact<{ [key: string]: never; }>;


Expand Down Expand Up @@ -346,6 +359,11 @@ export type GetReservationsByArticleIdQueryVariables = Exact<{

export type GetReservationsByArticleIdQuery = { __typename?: 'Query', getReservationsByArticleId: Array<{ __typename?: 'Reservation', id: string, startDate: any, endDate: any, createdAt: any, status: string, articles: Array<{ __typename?: 'Article', id: string, product: { __typename?: 'Product', name: string } }>, user: { __typename?: 'User', email: string } }> };

export type GetAllReservationsQueryVariables = Exact<{ [key: string]: never; }>;


export type GetAllReservationsQuery = { __typename?: 'Query', getAllReservations: Array<{ __typename?: 'Reservation', startDate: any, endDate: any, user: { __typename?: 'User', firstname: string, lastname: string }, articles: Array<{ __typename?: 'Article', product: { __typename?: 'Product', name: string } }> }> };


export const CreateNewProductDocument = gql`
mutation CreateNewProduct($data: NewProductInput!) {
Expand Down Expand Up @@ -696,6 +714,37 @@ export function useHandleReservationMutation(baseOptions?: Apollo.MutationHookOp
export type HandleReservationMutationHookResult = ReturnType<typeof useHandleReservationMutation>;
export type HandleReservationMutationResult = Apollo.MutationResult<HandleReservationMutation>;
export type HandleReservationMutationOptions = Apollo.BaseMutationOptions<HandleReservationMutation, HandleReservationMutationVariables>;
export const CanDeleteArticleDocument = gql`
mutation CanDeleteArticle($articleId: String!) {
canDeleteArticle(articleId: $articleId)
}
`;
export type CanDeleteArticleMutationFn = Apollo.MutationFunction<CanDeleteArticleMutation, CanDeleteArticleMutationVariables>;

/**
* __useCanDeleteArticleMutation__
*
* To run a mutation, you first call `useCanDeleteArticleMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useCanDeleteArticleMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [canDeleteArticleMutation, { data, loading, error }] = useCanDeleteArticleMutation({
* variables: {
* articleId: // value for 'articleId'
* },
* });
*/
export function useCanDeleteArticleMutation(baseOptions?: Apollo.MutationHookOptions<CanDeleteArticleMutation, CanDeleteArticleMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<CanDeleteArticleMutation, CanDeleteArticleMutationVariables>(CanDeleteArticleDocument, options);
}
export type CanDeleteArticleMutationHookResult = ReturnType<typeof useCanDeleteArticleMutation>;
export type CanDeleteArticleMutationResult = Apollo.MutationResult<CanDeleteArticleMutation>;
export type CanDeleteArticleMutationOptions = Apollo.BaseMutationOptions<CanDeleteArticleMutation, CanDeleteArticleMutationVariables>;
export const GetAllProductsDocument = gql`
query GetAllProducts {
getAllProducts {
Expand Down Expand Up @@ -1153,4 +1202,53 @@ export function useGetReservationsByArticleIdSuspenseQuery(baseOptions?: Apollo.
export type GetReservationsByArticleIdQueryHookResult = ReturnType<typeof useGetReservationsByArticleIdQuery>;
export type GetReservationsByArticleIdLazyQueryHookResult = ReturnType<typeof useGetReservationsByArticleIdLazyQuery>;
export type GetReservationsByArticleIdSuspenseQueryHookResult = ReturnType<typeof useGetReservationsByArticleIdSuspenseQuery>;
export type GetReservationsByArticleIdQueryResult = Apollo.QueryResult<GetReservationsByArticleIdQuery, GetReservationsByArticleIdQueryVariables>;
export type GetReservationsByArticleIdQueryResult = Apollo.QueryResult<GetReservationsByArticleIdQuery, GetReservationsByArticleIdQueryVariables>;
export const GetAllReservationsDocument = gql`
query GetAllReservations {
getAllReservations {
startDate
endDate
user {
firstname
lastname
}
articles {
product {
name
}
}
}
}
`;

/**
* __useGetAllReservationsQuery__
*
* To run a query within a React component, call `useGetAllReservationsQuery` and pass it any options that fit your needs.
* When your component renders, `useGetAllReservationsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useGetAllReservationsQuery({
* variables: {
* },
* });
*/
export function useGetAllReservationsQuery(baseOptions?: Apollo.QueryHookOptions<GetAllReservationsQuery, GetAllReservationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<GetAllReservationsQuery, GetAllReservationsQueryVariables>(GetAllReservationsDocument, options);
}
export function useGetAllReservationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetAllReservationsQuery, GetAllReservationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<GetAllReservationsQuery, GetAllReservationsQueryVariables>(GetAllReservationsDocument, options);
}
export function useGetAllReservationsSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions<GetAllReservationsQuery, GetAllReservationsQueryVariables>) {
const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}
return Apollo.useSuspenseQuery<GetAllReservationsQuery, GetAllReservationsQueryVariables>(GetAllReservationsDocument, options);
}
export type GetAllReservationsQueryHookResult = ReturnType<typeof useGetAllReservationsQuery>;
export type GetAllReservationsLazyQueryHookResult = ReturnType<typeof useGetAllReservationsLazyQuery>;
export type GetAllReservationsSuspenseQueryHookResult = ReturnType<typeof useGetAllReservationsSuspenseQuery>;
export type GetAllReservationsQueryResult = Apollo.QueryResult<GetAllReservationsQuery, GetAllReservationsQueryVariables>;
6 changes: 6 additions & 0 deletions frontend/src/graphql/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,9 @@ export const HANDLE_RESERVATION = gql`
}
}
`;

export const CAN_DELETE_ARTICLE = gql`
mutation CanDeleteArticle($articleId: String!) {
canDeleteArticle(articleId: $articleId)
}
`;
86 changes: 55 additions & 31 deletions frontend/src/graphql/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,32 +72,38 @@ export const LOGOUT = gql`
export const GET_RESERVATIONS_BY_USER_ID = gql`
query GetReservationsByUserId {
getReservationsByUserId {
reservation
{id
startDate
endDate
status
articles {
reservation {
id
}}
startDate
endDate
status
articles {
id
}
}
totalPrice
}
}
`;

export const SEARCH_AND_FILTER_PRODUCTS = gql`
query SearchAndFilterProducts($dateRangeInput: ProductDateRangeInput, $keyword: String) {
searchAndFilterProducts(dateRangeInput: $dateRangeInput, keyword: $keyword) {
id
name
description
price
imgUrl
query SearchAndFilterProducts(
$dateRangeInput: ProductDateRangeInput
$keyword: String
) {
searchAndFilterProducts(
dateRangeInput: $dateRangeInput
keyword: $keyword
) {
id
name
description
price
imgUrl
}
}
}
`;


export const GET_CURRENT_RESERVATION_BY_USER_ID = gql`
query GetCurrentReservationByUserId {
getCurrentReservationByUserId {
Expand All @@ -121,24 +127,42 @@ export const GET_CURRENT_RESERVATION_BY_USER_ID = gql`
}
`;


export const GET_RESERVATIONS_BY_ARTICLE_ID = gql`
query GetReservationsByArticleId($articleId: ID!) {
getReservationsByArticleId(articleId: $articleId) {
id
articles {
query GetReservationsByArticleId($articleId: String!) {
getReservationsByArticleId(articleId: $articleId) {

id
product {
name
articles {
id
product {
name
}
}
startDate
endDate
createdAt
status
user {
email
}
}
startDate
endDate
createdAt
status
user {
email
}
`;

export const GET_ALL_RESERVATIONS = gql`
query GetAllReservations {
getAllReservations {
startDate
endDate
user {
firstname
lastname
}
articles {
product {
name
}
}
}
}
}
`;
`;
3 changes: 2 additions & 1 deletion frontend/src/pages/Admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Tabs, Typography } from "antd";
import NewProduct from "./NewProduct";
import NewArticle from "./NewArticle";
import { useMediaQuery } from "react-responsive";
import HandleReservations from "./HandleReservations";

const { Title } = Typography;

Expand All @@ -22,7 +23,7 @@ function Admin() {
{
key: "3",
label: "Gérer les réservations",
children: "à venir",
children: <HandleReservations />,
},
];

Expand Down
Loading
Loading