Snai3i-LandingPage-FormBuilder / backend / src / controllers / formResponseController.ts
formResponseController.ts
Raw
import type { NextFunction, Request, Response } from 'express';
import FormResponse, { FormResponseI } from '../models/formResponseModel';
import Form from '../models/formModel';
import Logger from '../utils/logger';
import { ErrorResponse, SuccessResponse } from '../utils/response';
import { HttpCodes } from '../config/errors';
import { parseAsync } from 'json2csv'

export const getAllResponses = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const formId = req.params.id;
  
  try {
    const form = await Form.findById(formId);
    if (!form) {
      Logger.error('No form found with that ID');
      return ErrorResponse(
        res,
        HttpCodes.NotFound.code,
        'No form found with that ID'
      );
    }

    const responses = await FormResponse.find({ form: formId }).exec();

    Logger.info(
      `Successfully retrieved all responses for the form with ID: ${formId}`
    );
    SuccessResponse(
      res,
      HttpCodes.OK.code,
      { responses },
      `Successfully retrieved all responses for the form with ID: ${formId}`
    );
  } catch (error) {
    Logger.error(`Failed to retrieve responses - ${error}`);
    return ErrorResponse(
      res,
      HttpCodes.InternalServerError.code,
      'Failed to retrieve responses. Please try again!'
    );
  }
};

export const createResponse = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const { response } = req.body;
  const formId = req.params.id;

  try {
    const form = await Form.findById(formId);
    if (!form) {
      Logger.error(`No form found with that ID - ${formId}`);
      return ErrorResponse(
        res,
        HttpCodes.NotFound.code,
        'No form found with that ID'
      );
    }

    if (!form.isActive) {
      Logger.error(`Form is not active - ${formId}`);
      return ErrorResponse(
        res,
        HttpCodes.BadRequest.code,
        `The form is no longer accepting submissions.`
      );
    }

    const newResponse = await FormResponse.create({
      form: formId,
      response,
    });

    Logger.info(`Response created successfully.`);
    return SuccessResponse(
      res,
      HttpCodes.Created.code,
      { response: newResponse },
      'Response created successfully.'
    );
  } catch (error) {
    Logger.error(`Failed to create response - ${error}`);
    return ErrorResponse(
      res,
      HttpCodes.InternalServerError.code,
      'Failed to create response. Please try again!'
    );
  }
};

export const exportFormResponses = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const formId = req.params.id;

  if (!formId) {
    Logger.error(`Failed to export form - Form ID not provided.`);
    return ErrorResponse(
      res,
      HttpCodes.BadRequest.code,
      'Please provide a form ID to export.'
    );
  }

  try {
    const formResponses: FormResponseI[] = await FormResponse.find({
      form: formId,
    });
    if (!formResponses) {
      Logger.error(`Failed to export formResponses - Form not found.`);
      return ErrorResponse(
        res,
        HttpCodes.NotFound.code,
        'Failed to export formResponses - Form not found.'
      );
    }

    // formResponsesMap => [{question: answer, question: answer, ...}, ...]
    const formResponsesMap = formResponses.map((response) => {
      const responseObj: { [key: string]: any } = {};
      response.response.forEach((element) => {
        responseObj[element.question] = element.answer;
      });
      return responseObj;
    });

    // formResponsesArray => [{question: answer, question: answer, ...}, ...]
    const formResponsesArray = formResponses.map((response) => {
      return response.response;
    });

    const csv = await parseAsync(formResponsesMap);
    // const csv = await parseAsync(formResponsesMap, { fields });
      
    // csvWithSep => to open in excel with correct formatting
    const csvWithSep = `sep=,\n${csv}`


    res.setHeader('Content-Type', 'text/csv');
    res.setHeader(
      'Content-Disposition',
      `attachment; filename=${formId}responses.csv`
    );

    

    res.status(HttpCodes.OK.code).send(csvWithSep);
    Logger.info(`Form responses exported successfully.`);

  } catch (error) {
    Logger.error(`Failed to export formResponses - ${error}`);
    return ErrorResponse(
      res,
      HttpCodes.InternalServerError.code,
      'Failed to export formResponses. Please try again!'
    );
  }
};