What is the best way to generate a timesheet while linking each data entry to its corresponding date?

Looking to create a timesheet grid that shows the current week and the project being worked on, similar to this example: https://jsfiddle.net/ho9a8neq/ How can I use v-model to accurately send the value along with the corresponding date to a database? Something like:

[
  {date: "jan-1": 8, project: 1},
  {date: "jan-2": 10, project: 1},
  {date: "jan-3": 10, project: 2}
]

Answer №1

In order to efficiently gather data for multiple projects over time and keep track of each day within them, I have devised the following data structure:

day = ''
week = [day, day, day]
project = [week, week, ...]

For simplicity's sake, it only allows for adding future weeks. While it can be modified to accommodate more flexibility, doing so would increase complexity in the models without necessarily enhancing understanding of how to link data to the model.

Each week should have a model that stores daily data using an array of empty strings:

week: ['','','','','','','']

Multiple weeks can be included in each project:

data: [week, week, week]

When a user creates a new project, it should replicate the current project model based on the active week:

_.cloneDeep(project(this.weekNum, this.rows.length))

With the data structure set up, it is time to link the view to it:

<input type="text" style="width: 35px;" v-model="row.data[weekNum][i]">

Please refer to the snippet below to understand how everything connects together:

const weekData = () => new Array(7).fill('');

const project = (weekNum, id) => ({
  project: "first",
  id,
  data: Array(weekNum + 1).fill([]).map(weekData)
});

new Vue({
  el: "#app",
  data: {
    weekNum: 0,
    rows: [_.cloneDeep(project(0, 0))]
  },
  methods: {
    addProject() {
      window.pp = _.cloneDeep(
          project(this.weekNum, this.rows.length)
        )
      this.rows.push(
        window.pp
      );
    },
    deleteRow(key) {
      this.rows.splice(key, 1);
    },
    nextWeek() {
      this.weekNum++;
      this.rows.forEach(_project => {
        if (!_project.data[this.weekNum]) {
          _project.data.push(weekData());
        }
      });
    },
    prevWeek() {
      this.weekNum--;
      this.rows.forEach(row => {
        if (!row.data[this.weekNum]) {
          row.data.unshift(weekData());
        }
      });
    },
    dates(dateFormat, weekNumber) {
      let startOfWeek = moment().startOf('week').add(weekNumber, "week");
      const endOfWeek = moment().endOf('week').add(weekNumber, "week");
      const days = [];
      while (startOfWeek <= endOfWeek) {
        days.push(startOfWeek.format(dateFormat))
        startOfWeek = startOfWeek.clone().add(1, 'd');
      }
      return days
    },
    log() {
      const output = _.reduce(this.rows, (result, row) => {
        const project = {
          project: row.id
        };
        const startWeek = moment().startOf('week');
        const weekDays = [];
        row.data.forEach((week, weekIdx) => {
          week.forEach((data, dataIdx) => {
            if (data === '') return;
            weekDays.push({
              data,
              project: row.id,
              day: startWeek.clone().add(weekIdx, 'week').add(dataIdx, 'd').format('MMM D')
            });
          });
        });
        return [...result, ...weekDays];
      }, []);
      console.log(output)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0a6765676f647e4a3824383e243a">[email protected]</a>/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b1ddded5d0c2d9f1859f80869f8080">[email protected]</a>/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="80f6f5e5c0b2aeb5aeb2b2">[email protected]</a>/dist/vue.min.js"></script>

<div id="app">
  <!-- for the sake of simplicity limit the date to future weeks -->
  <button @click="prevWeek" :disabled="weekNum < 1">Previous week</button>
  <button @click="nextWeek">Next week</button>
  <button @click="addProject">Add project</button>
  <table>
    <tr>
      <th>Project</th>
      <th v-for="(day, i) in dates('MMM D', weekNum)" :key="i">{{day}}</th>
    </tr>
    <tbody>
      <tr v-for="(row, key) in rows" :key="key">
        <td>Project {{key}}</td>
        <td v-for="(n,i) in dates('YYYY-MM-DD', weekNum)" :key="`${row.id}-${i}`">
          <input type="text" style="width: 35px;" v-model="row.data[weekNum][i]">
        </td>
        <td><button @click="deleteRow(key)">x</button></td>
      </tr>
    </tbody>
  </table>
  <button @click="log()">log</button>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leveraging JQuery to extract the numerical value located between the slashes within a hyperlink

I need to extract numeric values from a link like this. For example: /produkt/114664/bergans-of-norway-airojohka-jakke-herre In this case, I want to fetch 114664. To achieve this, I have written the following jQuery code: jQuery(document).ready(functi ...

"Printed within the custom directive, the ng model value shows up as undefined

I am currently in the process of creating a custom directive that involves a simple template consisting of an input type textarea. I am assigning the ng-model to ngmodel and creating a link function where I am trying to capture the value of ngmodel. Howeve ...

Utilize angular to call a function when navigating

Having an issue with ChartJS while creating a chart using angular. The problem arises when navigating to a new page and then back to the original one, as the JavaScript is not triggered again. Is there a way to automatically invoke a JavaScript function o ...

Display a dynamic creation of a "object/canvas" utilizing Three.js embedded within a DIV element

Check out this Code: I have a dynamic "object" created in Canvas using Three.js, but it's currently appearing at the bottom of the page, just before the closing </body> tag. How can I adjust its position so that it loads inside the "<div id= ...

Tips for expanding a fabric canvas to match the entire width of its parent division

specific scenario I have a cloth canvas placed inside a main section. How can I expand the canvas to cover the entire width and height of its container? Here is what my current code looks like: <div class="design_editor_div"> &l ...

Only the (click) event is functional in Angular, while the (blur), (focus), and (focusout) events are not functioning

I have a unique HTML element as shown below <div (hover)="onHover()" (double-click)="onDoubleClick()" (resize)="resize()" (dragend)="dragEnd()"> These 4 functions are designed to display information onHover ...

Update the contents of a webpage using AJAX

Can anyone help me with loading likes into a div using AJAX every second? I want the page's URL to be likes.php?p=0 on page load, likes.php?p=1 after 1 second, likes.php?p=2 after 2 seconds, and so on. This is my code snippet: var loadLikes = func ...

What is the best way to determine if a value is missing in JavaScript and then stop the function while displaying an

I am currently working on designing a website and I am in need of a specific function that will halt if one input value is missing and then display an error message accordingly. Below is the HTML code for the form I am working on: <form action="htt ...

Is it possible to automatically submit a form at regular intervals without reloading the page and simultaneously insert the submitted data into

I am attempting to automatically submit a form every x number of seconds without refreshing the page and then insert the input data into a MYSQL database. The problem I'm facing is that while I can successfully insert the form's input value into ...

Exploring node.js: How to extract elements from a path

I have an array of individuals as shown below: individuals = ['personA', 'personB', 'personC']; I am looking to create a dynamic way to showcase each individual's page based on the URL. For instance, localhost:3000/indi ...

Guide to updating information in Firestore using Node.js, embedded in a map array

Encountered an issue with the following error message: Error: Unable to access 'set' property of undefined. I am attempting to update the endTime field in my script for each user, calculate total hours worked, and then update the 'totalTi ...

How can I save the content from a tiptap editor in a PHP form?

I'm looking to integrate the TipTap editor into a PHP form as a textarea field. I've set up a Vue component and passed it to the blade view. Blade view: <form method="post" action="{{ route('dashboard.edit.postInfo', ...

Angular input range slider that automatically rounds decimal values from the data bindings

I've implemented a range slider within an Angular form to capture and display recorded values. <input [formControlName]="object.id" [id]="object.id" type="range" [(ngModel)]="object.answer" [step]="objec ...

What could be causing the error message "@vue/composition-api/dist/vue-composition-api.mjs Not Found" to appear every time I

I received a Vue.js project from my vendor and have downloaded all the necessary packages using npm install. However, when I attempt to run npm run dev, I consistently receive the following error message: This dependency was not found: @vue/composition-a ...

Redefining a path in JavaScript after the page has already loaded

I am currently facing an issue with my website, which is built in HTML. In the head tag, I have included a JavaScript file. The website consists of two pages, and the problem arises when the path defined in the JavaScript file works correctly on the first ...

Turning off devtools in Next.js

Currently, my focus is on developing an application using Next.js and I am in search of a way to prevent the opening of devtools. While exploring npm packages, I came across a promising tool called Disable-devtool - npm link. However, Next.js keeps present ...

When attempting to perform conditional rendering in React using a stateless functional component, I encounter an error stating "Unexpected token, expected ,"

Here is the code snippet: 'use strict' import React from 'react' import { connect } from 'react-redux' import { Panel, Col, Row, Well, Button } from 'react-bootstrap' const Cart = ({ cart }) => { const cartI ...

Is there a way to submit two forms using just one button?

I have a unique challenge where I need to submit 2 forms using just one button within the Spring MVC framework. Here is the structure of my JSP page: <form:form id="form1" method="POST" modelAttribute="employee" ...

Can NodeJS Handle Image Processing and Analysis?

I am currently running NodeJS on the server-side, and I am attempting to automate the process of determining the 'base color' of an image. My goal is to accomplish this by following these steps: Retrieve an image (located on a remote server, h ...

Combining Vue 2 with Bootstrap-vue to create interactive and dynamic attributes

Hello everyone, I'm excited to be taking my first steps in Vue 2 alongside bootstrap-vue. Currently, I am trying to dynamically change the name of an attribute in order to adjust the tooltip position for smaller screen resolutions. The JS code below ...