diff --git a/amplify/backend/function/contactslambda/src/app.js b/amplify/backend/function/contactslambda/src/app.js index 5bfbbd5670948345bfedbb381abb2263714f2c52..7c9397a0345e3dda39821408354df174dcccb40c 100644 --- a/amplify/backend/function/contactslambda/src/app.js +++ b/amplify/backend/function/contactslambda/src/app.js @@ -15,6 +15,7 @@ const { QueryCommand, UpdateCommand, ScanCommand, + BatchWriteCommand, } = require("@aws-sdk/lib-dynamodb"); const awsServerlessExpressMiddleware = require("aws-serverless-express/middleware"); const bodyParser = require("body-parser"); @@ -89,55 +90,13 @@ app.get(path, async function (req, res) { } }); -/************************************ - * HTTP Get method to query objects * - ************************************/ -/* -app.get(path + hashKeyPath, async function (req, res) { - const condition = {}; - condition[partitionKeyName] = { - ComparisonOperator: "EQ", - }; - - if (userIdPresent && req.apiGateway) { - condition[partitionKeyName]["AttributeValueList"] = [ - req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH, - ]; - } else { - try { - condition[partitionKeyName]["AttributeValueList"] = [ - convertUrlType(req.params[partitionKeyName], partitionKeyType), - ]; - } catch (err) { - res.statusCode = 500; - res.json({ error: "Wrong column type " + err }); - } - } - - let queryParams = { - TableName: tableName, - KeyConditions: condition, - }; - - try { - const data = await ddbDocClient.send(new QueryCommand(queryParams)); - res.json(data.Items); - } catch (err) { - res.statusCode = 500; - res.json({ error: "Could not load items: " + err.message }); - } -}); - */ /***************************************** * HTTP Get method for get single object * *****************************************/ app.get(path + hashKeyPath, async function (req, res) { const params = {}; - /* if (userIdPresent && req.apiGateway) { - params[partitionKeyName] = - req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH; - } else { */ + params[partitionKeyName] = req.params[partitionKeyName]; try { params[partitionKeyName] = convertUrlType( @@ -148,18 +107,6 @@ app.get(path + hashKeyPath, async function (req, res) { res.statusCode = 500; res.json({ error: "Wrong column type " + err }); } - /* } */ - /* if (hasSortKey) { - try { - params[sortKeyName] = convertUrlType( - req.params[sortKeyName], - sortKeyType - ); - } catch (err) { - res.statusCode = 500; - res.json({ error: "Wrong column type " + err }); - } - } */ let getItemParams = { TableName: tableName, @@ -189,15 +136,6 @@ app.put(path + "/edit", async function (req, res) { if (userIdPresent) { req.body["userId"] = userId || UNAUTH; } - - /* // Check if there is an image update - if (req.body.image) { - // Update the image in S3 - const imageUrl = await uploadImageToS3(userId, req.body.image); - req.body["image"] = imageUrl; - } */ - - // Build the UpdateExpression and ExpressionAttributeValues dynamically const updateExpression = []; const expressionAttributeNames = {}; const expressionAttributeValues = {}; @@ -221,8 +159,6 @@ app.put(path + "/edit", async function (req, res) { ExpressionAttributeValues: expressionAttributeValues, }; - console.log("updateitemParams", updateItemParams); - let data = await ddbDocClient.send(new UpdateCommand(updateItemParams)); res.json({ success: "put call succeed!", url: req.url, data: data }); @@ -259,12 +195,9 @@ app.post(path, async function (req, res) { * HTTP remove method to delete object * ***************************************/ -app.delete(path + hashKeyPath, async function (req, res) { +app.delete(path + "/delete" + hashKeyPath, async function (req, res) { const params = {}; - /* if (userIdPresent && req.apiGateway) { - params[partitionKeyName] = - req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH; - } else { */ + params[partitionKeyName] = req.params[partitionKeyName]; try { params[partitionKeyName] = convertUrlType( @@ -275,18 +208,6 @@ app.delete(path + hashKeyPath, async function (req, res) { res.statusCode = 500; res.json({ error: "Wrong column type " + err }); } - /* } */ - /* if (hasSortKey) { - try { - params[sortKeyName] = convertUrlType( - req.params[sortKeyName], - sortKeyType - ); - } catch (err) { - res.statusCode = 500; - res.json({ error: "Wrong column type " + err }); - } - } */ let removeItemParams = { TableName: tableName, @@ -310,8 +231,6 @@ app.patch(path + "/updateFavorite" + hashKeyPath, async function (req, res) { } const { isFavorite, contactsid } = req.body; - console.log("contactId", req.body[partitionKeyName]); - // Update item in DynamoDB const updateItemParams = { TableName: tableName, @@ -328,8 +247,6 @@ app.patch(path + "/updateFavorite" + hashKeyPath, async function (req, res) { ReturnValues: "ALL_NEW", }; - console.log("updateFavorite", updateItemParams); - const data = await ddbDocClient.send(new UpdateCommand(updateItemParams)); // Extract only the isFavorite value @@ -348,6 +265,47 @@ app.patch(path + "/updateFavorite" + hashKeyPath, async function (req, res) { } }); +app.delete(path + "/batch-remove", async function (req, res) { + const userId = getUserId(req); + if (userIdPresent) { + req.body["userId"] = userId || UNAUTH; + } + + const contactIdsToDelete = req.body.contactsids; + + if (!contactIdsToDelete || !Array.isArray(contactIdsToDelete)) { + res.statusCode = 400; + res.json({ + error: "Invalid or missing contactIds array in the request body", + }); + return; + } + + const deleteRequests = contactIdsToDelete.map((contactId) => { + return { + DeleteRequest: { + Key: { + [partitionKeyName]: contactId, + }, + }, + }; + }); + + const params = { + RequestItems: { + [tableName]: deleteRequests, + }, + }; + + try { + let data = await ddbDocClient.send(new BatchWriteCommand(params)); + res.json({ url: req.url, data: data }); + } catch (err) { + res.statusCode = 500; + res.json({ error: err, url: req.url }); + } +}); + app.listen(3000, function () { console.log("App started"); }); diff --git a/amplify/team-provider-info.json b/amplify/team-provider-info.json index 2d228f481a13da741728e314145751c97a3615de..068b26f34571e18d190623330b7d48475e352db2 100644 --- a/amplify/team-provider-info.json +++ b/amplify/team-provider-info.json @@ -19,7 +19,7 @@ "function": { "contactslambda": { "deploymentBucketName": "amplify-contactappamplify-dev-165436-deployment", - "s3Key": "amplify-builds/contactslambda-7370382b67386a35514a-build.zip" + "s3Key": "amplify-builds/contactslambda-7848723554716e326f54-build.zip" }, "labelslambda": { "deploymentBucketName": "amplify-contactappamplify-dev-165436-deployment", diff --git a/src/api/asyncFunctions/contacts/index.tsx b/src/api/asyncFunctions/contacts/index.tsx index 3b1c6f538252b51d3436a49e72312714c5c5112f..94a6c97dd59007e06c5efb6b0d5be44d53349161 100644 --- a/src/api/asyncFunctions/contacts/index.tsx +++ b/src/api/asyncFunctions/contacts/index.tsx @@ -33,36 +33,6 @@ export async function getAllContactApi(): Promise< } } -export async function getAllContactsWithSpecificLabelApi( - labels: string -): Promise<{ data: ContactEntry[] } | { error: FetchBaseQueryError }> { - try { - const data = await API.get( - contactsApi, - `/contacts/labels?labels=${encodeURIComponent(labels)}`, - {} - ); - return { data: data }; - } catch (err) { - return { - error: err as FetchBaseQueryError, - }; - } -} - -export async function getListOfFavoriteContactApi(): Promise< - { data: ContactEntry[] } | { error: FetchBaseQueryError } -> { - try { - const data = await API.get(contactsApi, "/contacts/favorite", {}); - return { data: data }; - } catch (err) { - return { - error: err as FetchBaseQueryError, - }; - } -} - export async function getSingleContactApi( contactsid: string ): Promise<{ data: ContactEntry } | { error: FetchBaseQueryError }> { @@ -76,45 +46,6 @@ export async function getSingleContactApi( } } -export async function getTotalCountContactApi(): Promise< - { data: number } | { error: FetchBaseQueryError } -> { - try { - const data = await API.get(contactsApi, "/contacts/count-all", {}); - return { data }; - } catch (err) { - return { - error: err as FetchBaseQueryError, - }; - } -} - -export async function getTotalCountForFavoriteContactApi(): Promise< - { data: number } | { error: FetchBaseQueryError } -> { - try { - const data = await API.get(contactsApi, "/contacts/count-favorite", {}); - return { data }; - } catch (err) { - return { - error: err as FetchBaseQueryError, - }; - } -} - -export async function getTotalCountForContactLabelApi(): Promise< - { data: number } | { error: FetchBaseQueryError } -> { - try { - const data = await API.get(contactsApi, `/contacts/count-label`, {}); - return { data }; - } catch (err) { - return { - error: err as FetchBaseQueryError, - }; - } -} - export async function updateSingleContactApi( contact: ContactEntry ): Promise<{ data: any } | { error: FetchBaseQueryError }> { @@ -156,7 +87,11 @@ export async function deleteSingleContactApi( contactId: string ): Promise<{ data: any } | { error: FetchBaseQueryError }> { try { - const data = await API.del(contactsApi, `/contacts/${contactId}`, {}); + const data = await API.del( + contactsApi, + `/contacts/delete/${contactId}`, + {} + ); return { data: data }; } catch (err) { return { @@ -166,11 +101,11 @@ export async function deleteSingleContactApi( } export async function batchDeleteContactApi( - contactIds: string[] + ids: string[] ): Promise<{ data: any } | { error: FetchBaseQueryError }> { try { const data = await API.del(contactsApi, `/contacts/batch-remove`, { - body: { contactIds: contactIds }, + body: { contactsids: ids }, }); return { data: data }; } catch (err) { diff --git a/src/api/contacts/index.tsx b/src/api/contacts/index.tsx index ec9c360abbf3b7c00520c2f05a5c777711234391..27235fec9a768d7b882c27c3d8e4b0ce5ebd340f 100644 --- a/src/api/contacts/index.tsx +++ b/src/api/contacts/index.tsx @@ -3,12 +3,7 @@ import { createContactApi, deleteSingleContactApi, getAllContactApi, - getAllContactsWithSpecificLabelApi, - getListOfFavoriteContactApi, getSingleContactApi, - getTotalCountContactApi, - getTotalCountForContactLabelApi, - getTotalCountForFavoriteContactApi, updateIsFavoriteStatusContactApi, updateSingleContactApi, batchDeleteContactApi, @@ -24,30 +19,10 @@ const contactsApiEndpoints = api.injectEndpoints({ queryFn: getAllContactApi, providesTags: ["Contacts"], }), - getAllContactsWithSpecificLabel: build.query({ - queryFn: getAllContactsWithSpecificLabelApi, - providesTags: ["Contacts"], - }), - getListOfFavoriteContacts: build.query({ - queryFn: getListOfFavoriteContactApi, - providesTags: ["Contacts"], - }), getSingleContact: build.query({ queryFn: getSingleContactApi, providesTags: ["Contacts"], }), - getTotalCountContacts: build.query({ - queryFn: getTotalCountContactApi, - providesTags: ["Contacts"], - }), - getTotalCountForFavoriteContacts: build.query({ - queryFn: getTotalCountForFavoriteContactApi, - providesTags: ["Contacts"], - }), - getTotalCountForContactLabel: build.query({ - queryFn: getTotalCountForContactLabelApi, - providesTags: ["Contacts"], - }), updateSingleContact: build.mutation({ queryFn: updateSingleContactApi, invalidatesTags: ["Contacts"], @@ -74,10 +49,5 @@ export const { useUpdateSingleContactMutation, useDeleteSingleContactMutation, useUpdateIsFavoriteStatusContactMutation, - useGetListOfFavoriteContactsQuery, - useGetTotalCountContactsQuery, - useGetTotalCountForFavoriteContactsQuery, - useGetAllContactsWithSpecificLabelQuery, - useGetTotalCountForContactLabelQuery, useBatchDeleteContactMutation, } = contactsApiEndpoints; diff --git a/src/pages/contactsList/index.tsx b/src/pages/contactsList/index.tsx index 62455ca5f53c0a5c44baca98cb800e77bc6f0817..bb523712bae853da3638350e2ac5b241a6e5e325 100644 --- a/src/pages/contactsList/index.tsx +++ b/src/pages/contactsList/index.tsx @@ -16,8 +16,6 @@ import { useBatchDeleteContactMutation, } from "api/contacts"; -/* import { useAppSelector } from "hooks/storeHooks"; -import { useAuthenticator } from "@aws-amplify/ui-react"; */ import { ContactEntry } from "types"; import firstCharToUpperCase from "utils/firstCharToUpperCase"; @@ -26,22 +24,20 @@ export default function AllContacts() { const [pageSize, setPageSize] = useState<number>(5); const [selectedIds, setSelectedIds] = useState<string[]>([]); - /* const [shownData, setShownData] = useState<ContactEntry[]>([]); - - const { user } = useAuthenticator((context) => [context.user]); */ - const { data: allContactsData, isLoading: allContactsLoading } = useGetAllContactsQuery(undefined); + const [batchDeleteContact] = useBatchDeleteContactMutation(); + const [deleteOneContact] = useDeleteSingleContactMutation(); const [updateIsFavoriteStatusContact] = useUpdateIsFavoriteStatusContactMutation(); const [getConfirmation, Confirmation] = useConfirmDialog(); const navigate = useNavigate(); - console.log(allContactsData); + function filterContacts(data: ContactEntry[]) { - const parts = pathname.split("/"); + const parts = pathname.split("/").filter(Boolean); const urlTarget = parts[parts.length - 1]; if (urlTarget === "list") { @@ -53,21 +49,22 @@ export default function AllContacts() { return favoriteContacts; } else { const filteredContactsByLabel = data.filter((contact) => { - contact.labels.map((label) => { - console.log(label); - }); - return contact.labels.some( (label) => label === firstCharToUpperCase(urlTarget) ); }); - console.log(filteredContactsByLabel); return filteredContactsByLabel; } } - const handleBatchDelete = () => { - console.log("handleBatchDelete", selectedIds); + const handleBatchDelete = async () => { + const isConfirmed = await getConfirmation({ + title: "Delete contacts", + contentText: "Are you sure you want to delete these contacts?", + confirmLabel: `Delete`, + }); + console.log(selectedIds); + if (isConfirmed) batchDeleteContact(selectedIds); }; const handleFavorite = (contact: ContactEntry) => { @@ -117,7 +114,7 @@ export default function AllContacts() { rows={filteredContacts || []} columns={columns} loading={allContactsLoading} - getRowId={(row) => row.email} + getRowId={(row) => row.contactsid} components={{ Toolbar: DataGridToolbar }} componentsProps={{ toolbar: {