ankitbisen28 / Atelier

Letest web app for custom clothing, Using React vite and Nodejs
https://atelier-client.vercel.app/
0 stars 1 forks source link

Feature Request: Allow Makers to Withdraw Their Application with Confirmation #14

Open ankitbisen28 opened 1 week ago

ankitbisen28 commented 1 week ago

Description

Create a feature that allows makers to withdraw their application (bid) from a project. Before the application is withdrawn, the maker should be asked to confirm the action to prevent accidental withdrawals.

Requirements

  1. Withdraw Application Functionality:

    • Allow makers to withdraw their applications from projects they have bid on.
    • Display a "Withdraw Application" button next to the maker's application details.
    • Ensure that only the maker who placed the bid can withdraw it.
  2. Confirmation Prompt:

    • When the "Withdraw Application" button is clicked, display a confirmation prompt asking, "Are you sure you want to withdraw your application?"
    • Include "Yes" and "No" options in the confirmation prompt.
    • Only withdraw the application if the maker confirms the action by selecting "Yes".
  3. Application Withdrawal:

    • If the maker confirms the withdrawal, remove the bid from the database.
    • Display a success message indicating that the application has been successfully withdrawn.
    • Update the project details to reflect the withdrawal of the application.

Acceptance Criteria

Additional Information

Mockups / Examples

Provide any mockups or examples of the desired component if available.

Technical Requirements

Mongoose Schema for Reference

const mongoose = require('mongoose');

const projectSchema = mongoose.Schema({
    "title": String,
    "description": String,
    "requirements": String,
    "budget": Number,
    "deadline": Date,
    "consumerId": String, // Reference to the user who posted the project
    "category": String,
    "images": [
        {
            "url": String, // URL of the image stored in an external service
            "description": String, // Optional description of the image
            "uploadedAt": Date // Timestamp when the image was uploaded
        }
    ],
    "selectedBidder": String, // Reference to the selected bidder (if any)
    "status": String, // "open", "closed", "in progress", "completed"
    "createdAt": Date,
    "updatedAt": Date
});

projectSchema.virtual('id').get(function () {
    return this._id.toHexString();
});

projectSchema.set('toJSON', {
    virtuals: true,
});

module.exports = mongoose.model('project', projectSchema);

const bidSchema = mongoose.Schema({
    "project_id": { type: mongoose.Schema.Types.ObjectId, ref: 'project' },
    "maker_id": { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
    "bid_amount": Number,
    "proposal_text": String,
    "status": { type: String, enum: ['Pending', 'Accepted', 'Rejected'], default: 'Pending' },
    "created_at": { type: Date, default: Date.now },
    "updated_at": { type: Date, default: Date.now }
});

bidSchema.virtual('id').get(function () {
    return this._id.toHexString();
});

bidSchema.set('toJSON', {
    virtuals: true,
});

module.exports = mongoose.model('bid', bidSchema);

Steps to Implement

  1. Update Backend Endpoint:

    • Create an endpoint to handle application (bid) withdrawal requests.
    const express = require('express');
    const router = express.Router();
    const Bid = require('../models/bid');
    const { ensureAuthenticated } = require('../middleware/auth');
    
    router.delete('/bids/:id', ensureAuthenticated, async (req, res) => {
        try {
            const bid = await Bid.findById(req.params.id);
            if (!bid) {
                return res.status(404).json({ message: 'Bid not found' });
            }
            if (bid.maker_id.toString() !== req.user.id) {
                return res.status(403).json({ message: 'Unauthorized to withdraw this bid' });
            }
            await Bid.findByIdAndDelete(req.params.id);
            res.status(200).json({ message: 'Bid successfully withdrawn' });
        } catch (error) {
            res.status(500).json({ message: 'Failed to withdraw bid', error });
        }
    });
    
    module.exports = router;
  2. Update Frontend Component:

    • Add a "Withdraw Application" button and handle the confirmation prompt.
    import React from 'react';
    import axios from 'axios';
    
    const BidDetail = ({ bid, user }) => {
        const handleWithdrawApplication = async () => {
            if (window.confirm('Are you sure you want to withdraw your application?')) {
                try {
                    await axios.delete(`/api/bids/${bid.id}`);
                    alert('Application successfully withdrawn');
                    // Update the UI to reflect the withdrawn application
                    window.location.reload();
                } catch (error) {
                    console.error('Failed to withdraw application', error);
                    alert('Failed to withdraw application');
                }
            }
        };
    
        return (
            <div>
                <p>{bid.proposal_text}</p>
                <p>Amount: {bid.bid_amount}</p>
                {user.id === bid.maker_id && (
                    <button onClick={handleWithdrawApplication}>Withdraw Application</button>
                )}
            </div>
        );
    };
    
    export default BidDetail;
  3. Integrate and Test:

    • Ensure the backend and frontend components are integrated correctly.
    • Test the feature thoroughly to ensure applications can be withdrawn as expected.

Tasks