Skip to content

Instantly share code, notes, and snippets.

@MonteLogic
Last active September 21, 2024 20:58
Show Gist options
  • Save MonteLogic/efa0f5458e3fc101751ab0776a18850e to your computer and use it in GitHub Desktop.
Save MonteLogic/efa0f5458e3fc101751ab0776a18850e to your computer and use it in GitHub Desktop.
Contractor Bud Writing

Contractor Bud Roadmap

We need to get the scheduling done good and then write docs, then release and then work on the other features.

todo-chamber-cb-work-notes-5

Read

Make sure you understand the tasks before starting it to understand the scope of the task.

When you are done with the tasks, write the branch name, the task id and the date accomplish, so

schedule-page, 0x2 Thu 23 May 2024 10:35:27 AM CDT

Project Goals

[

  • 2x - Get the route and date to be in a URL.

  • Date?

  • 2x - Enter a URL and have the search form bring up the route and/or Date which is in the URL.

  • Date?

  • 2x - Redirect everything to cbud.app

  • This was done with great difficulty, in the future, make a new app and point the old app to it rather than fiddling around with redirects within the same app.

  • 2x - Move schedule to /main [x] 2x - Get state to persist in /main.

  • - 2x - Home page of '/' which is going to say view app.

  • Date?

  • [-] - 2x4 - Private privileges on orgs and users.

  • Don't really know what this means

  • - 2x5 - Make invite to certain org capability.

  • Clerk provides this but I think I should make the process easier on a settings page.

  • I feel like this is a requirement of a scalable MVP.

  • - 2x6 - There could be an option where you could do all shifts. 1

  • - 2x7 - Add editing for, the put the user organization for /main/schedule.

  • - 2x8 - Create secret links.

  • - 2x8 - Write docs

  • - 2x9 - Make edit Routes page.

  • - 2x10 - Rework the schedule page to show the times and shifts created on the Routes page.

  • - 2x11 - Add spinning wheel for loading in top left corner.

  • - 2x12 - 05/16/24 - Add spinning wheel for loading in top left corner.

  • - 2x13 - Seek Invite, "And organizations go on the invite me to organization or invite page and to your ZIP code and they'll be like a larger and enlarged radius of all the companies in the area request a company and it automatically fill out your name and your location "

  • - 2x13 Move project from MySQL to SQLite as SQLite is easier and it will be easier for mobile and/or no internet development. Added: Thu 27 Jun 2024 02:55:50 PM CDT

]

Branches

Branch: routes-page

[

  • - 0x0 - Edit prior shifts, list all shifts, delete shifts.

]

Branch: summary-page

[

  • - 0x0 - Change color to white text on Summary page. - 10

]

Branch: testing-suite

[

  • - 0x0 - Test to show the modal has come up in main/schedule.

]

Branch: schedule-page

[

  • - 0x0 - Make the page have spinning wheel to wait for upload to db. - 20

  • - 0x1 - Make the route times show up.

  • - 0x2 - Only have shifts from allocatedShifts show up.

  • - 0x3 - Link to summary page via href

  • - 0x3 - Create tabbed content

  • - 0x4 - Tabbed content with Summary business logic.

  • - 0x4 - Tab within tab which says Truck summary.

  • - 0x5 - Add route name to schedule modal.

  • - 0x6 - Add the HCR 626M5 to more stuff on Schedule page to describe.

  • - 0x7 - On the initial load, it is showing white, make the preview show yellow or nothing as it's showing white, possibly memoize or something of this sort so a false showing of white, no work, won't show. - 30

  • - 0x8 - Write and run an effective visual test to show the sliders are still there as well as business logic in the modal.

  • - 0x9 - Create visual test.

  • - 0x10 - Change schedule to take in the current route form - Added: Wed 26 Jun 2024 01:02:11 PM CDT

  • - 0x10 - Make the schedule slider be movable by the scroll wheel. Added: Thu 27 Jun 2024 02:34:16 PM CDT

  • - 0x10 - Make it so that days which are already done are a different color than yellow. Added: Thu 27 Jun 2024 02:36:58 PM CDT High Priority

]

Notes: schedule-page

Issued PR: (05/16/24), not interested in doing 0x3. May delete summary page.

Branch: timecard-page

[

  • - 0x0 - Make the timecard functionality work for Enidan. - Link to the PDFs showing the examples.
  • - 0x1 - Show previous timecards
  • - 0x2 - Accept date as Param. - @MonteLogic
  • - 0x2 - Discriminate to only show the org employee which the user is in. - @MonteLogic
  • - 0x3 - [HIGH PRIORITY] Spreadsheets working for Enidan template. - @MonteLogic Added: Mon Jul 1 10:06:10 AM CDT 2024
  • - 0x2 - I would like to make a setting within the Settings page which sets the pay period so you can make it the 15th or the 1st, etc. - @MonteLogic

]

Now going to focus on the timecard page.

Footnotes

Footnotes

  1. I've found out that you have to register again with the post office to work for other companies. So switching isn't as common as I thought.

Contractor Buddy Work Notes - Part 5

Start: Thu 13 Jun 2024 01:54:42 PM CDT The project from now on is going to be focused on Test Driven Development.

Okay, so I am working on, going to back the schedule page where I will be modifying the modal by writing a test first to determine if the value is being saved in a timely manner and being kept in the relevant state vicinity.

test.describe("app", () => {
  test(
    "Sign in, open modal, navigate to the summary tab, write to the summary a random string, save it then close modal and reopen modal to see if the summary is still there."
  );
});

So, what I'm going to have to do is making it so that user is apart of a group which has schedule logic to it. We could make the seek invite functionality for new users work.

Once we get a working schedule view then we can go from there.

Start: Sun 16 Jun 2024 05:08:54 PM CDT

Just going thru the timecard process I believe the best thing to do is to focus more on timecards.

"Adding routes and can't add shifts because it doesn't show up on allocatedShifts."

When I tried to do timecards with cbud.app I couldn't, due to the fact that I couldn't add shifts to a route among many other app breaking bugs.

// Testing add route functionality, for this we will test if allocatedShifts show and in another test we will see if the shifts are showing on main/schedule.
// Add a route, take a picture and then delete the route.
test.describe('app', () => {
  test(
    '

    '
  ) })

Start: Mon 17 Jun 2024 09:32:51 AM CDT

Currently on Routes page.

Now working on routes-page-2.

Start: Wed 19 Jun 2024 05:24:06 PM CDT

For the test I need to have it in the dev Org rather than personal account.

I also wonder if you can record the Browser view from Playwright as a .mp4.

I don't think writing tests and having someone do the whole test correctly without changing the prospective test is doable. I still am very much interested in TDD though but the dev is going to have to change on Red Green Refactor.

I have to make the Route adding in realtime.

"Make updates to the DOM in realtime Next.js 13"

I saw on Stager's stream of how he would look up messages which were made on his stream so he had this huge db and he could search for a string I would like this same functionality but for my blog so I can look up my/our tutorials much quicker. get current org id clerk next.js

You need to create an API file as such: https://gist.github.com/MonteLogic/e60c6037b56045bdfc3ad5548ecdc39d

Or better yet, bring it in from the server component.

Start: Fri 21 Jun 2024 09:02:38 AM CDT

Working on adding routes and discriminating so routes are on relevant orgs.

Am still unable to make the route data show up right after clicking Add Route the only thing that shows is an empty entry.

Why is there an empty entry which adds on to the array but doesn't add the added data?

Okay, now that adding routes is good, ideally I would write a vRegression test for this.

But I need to get focused on why allocatedShifts isn't uploading to the db.

Now, what I've noticed is that the object being sent in isn't manicured to work well.

I could do the editing on the server to make the object parsable by the function.

Start: Tue Jun 25 01:46:38 PM CDT 2024

Trying to get the route addition parsable by the function which takes it in.

What on Earth is this 'active' bullsh*t?

Parsable: Allocated Shifts:

{
  "allocatedShifts": {
    "afternoon": { "end": "1830", "start": "1500", "active": 1 },
    "midMorning": { "end": "0800", "start": "0500", "active": 1 }
  }
}

Current: Allocated Shifts:

[
  { "name": "First trip", "startTime": "03:16", "endTime": "05:15" },
  { "name": "Second trip", "startTime": "07:15", "endTime": "08:15" }
]

Start: Wed 26 Jun 2024 10:39:43 AM CDT

I think I'm just going to change main/schedule to take in an array instead of an object. This will keep it as is.

Start: Thu 27 Jun 2024 10:26:11 AM CDT

How does the allocatedShift object even get parsed by the function and which function is it?

Ok, now an issue I'm having is that all of these windows are showing Jacksonville for some reason. I think the loop may only be able to handle two cause Pleasant Plains is showing fine.

The issue was I was iterating on route id from post office which may not be unique, so I was iterating on the same ones as Jacksonville cause they all had the same route id from post office.

I need to use the id as the reference point.

Where exactly is the comparison taking place which will use the route ID from post office? But whenever we find this we are going to replace it with the first six digits of the randomly generated ID in the ID row of the table

Start: Fri Jun 28 11:51:39 AM CDT 2024 Where exactly is the comparison for post office route id being made?

Whats going on with this? findRelevantEmployeeInfo(workTimeArray, routeIDFromPostOffice, date);

Where exactly is the comparison for post office route id being made?

    findRelevantEmployeeInfo(workTimeArray, routeIDFromPostOffice, date);

I'm just going to change it to .id from .routePostOfficeID and fix the breaks. I may use the full id rather than a shortened one, whats the point of using a shortend id value which was taken from the db?

Then fix the issues which may arise by using id as a comparison.

"routeIDFromPostOffice" eventaully becomes loopRelevantRoute

So changing routeIDFromPostOffice to idOfRouteDBGen

routeIDFromPostOffice

I want save to be on the right side also get rid of all that save/edit logic just save button shows up after and edit is made.

Also, dim and make unchangable if a slot is already taken by another employee and then possibly make a manager mode which is a switch at the top where you can switch it and change past and present slots which have been worked.

Okay, now its not saving.

Don't know why its not updating optimistically via the yellow changing of colors

• You are about to drop the column routeIDFromPostOffice on the WorkTime table, which still contains 195 non-null values. Dropping routeIDFromPostOffice bc it is not random enough for a delineator.

So now we need to get working on make the logic yellow based on the idOfRoute classification. Okay, so I fixed this problem by changing item.id to item.idOfRoute. Solved using console.logs.

I feel like it would be better to understand if the Day of the week was on top o f it like a card and it was a diffrent color.

See: https://montelogic.com/wp-content/uploads/2024/06/Day-of-week-cards-Screen-Shot-2024-06-28-at-14.37.01.png

Start: Mon Jul 1 09:40:03 AM CDT 2024

Okay, so my db is pulling way too many records from the db. We need to make it like 10x more effecient.

What next for schedule-page-2?

We need to get the spreadsheets working.

Select pay period range in days:

Should be replaced with, by default start of the month and end of the month set because it could be tricky if they hand pick it as 30.

I think I need to discriminate on orgId for the timecard page.

Looking for a calendar for the timecard page. This calendar will use Tailwind. Like the look of this: https://tailwindcomponents.com/component/custom-calendar

Made calendar work, still would like for it to say July and other things as well as being able to click on certain days and changing it.

Also have to set default values on this in Settings page.

Start: Tue Jul 2 09:42:35 AM CDT 2024

Okay let's get started on template building for timecards.

Which function is being called for the Enidan selection?

EnidanTemplatePDF

Timecard shows good but I need to make employee id selector better for timecard component.

Start pay period should be linked to the calendar selection of the first day so if the the calendar which says starting on: saying 07/01/2024 then it should start on the first viz. the start pay period.

I would like a light theme so we can view the app much easier in direct sunlight. But we need the MVP first.

Would really like a dial/ input on Schedule page to show the milage as well as t he truck id.

... What's happening is that the records aren't being deleted if there a row goes from worked to not worked.

Would like to add functionality which shows user there may be a time conflict viz. booking an employee on the same time slot but two different shifts.

Using pdf-lib and .tsx we are going to write over a pdf which has already been created.

Start
Wed Jul 3 10:51:51 AM CDT 2024

When we/I are/am wrapping up make sure to write down what you are working on and what to do next. So we are going to use pdf-lib on draw on already made pdfs.

... Let's move timecard menu item near schedule.

Okay, so let's just get it to draw whatever on it. ... Now we are going to white out the dates, Learned there is no 'erasing' out things using the rectangle in pdf-lib due to the fact that the data underneath is still there just whitened out.

After this we are going to replace them with the dates we selected earlier.

Okay, so pdf-lib DOES NOT work for erasing content.

...

Okay, let's get Driver name and put it into the PDF.

x and y positioning is good for this:

const x = 165;
const y = 702.1;

Now, let's get the pay period.

Working on the client side component:

For: 75 pay periods: 15 31 2024-07-03

The starting date which is for the pay period is on 2024-07-15 to 2024-07-31

The calendar logic should read the start pay period and show that one I feel lik e the start pay period should match for the user. The days should default/go to 1, or 15 for the starting day depending on what the current day in the calendar is.

But these additons could be added after the pdf, just deal with the "complicated" logic for now.

Start: Fri Jul 5 10:26:16 AM CDT 2024

I am working in the library and I am unable to get to my prod site, it may be a Namecheap thing cause I can't get on 'namecheap.com'

When I try to use the site from my nameceheap I get an SSL error but when I use the domain which I purchased from Vercel it works.

So I'm going to transfer out cbud.app when I get a chance because the down time is too much for Namecheap.

Now, we are going to put the Monday in the Monday slot. We are working on slotting logic.

So what it is exactly will we be discriminating? workTimeForEmployee:

console.log(77, "Work time data:", workTimeForEmployee);

Side note: I would really like a CLI for adding notes into the todo-area.

I would enter the branch and then find the task and mark it as complete or I wou ld add a task.

When it comes to this PDF, there's a lot of guess and check would be nice if I could get a hold of a pdf-lib reference where it says where in the pdf it will render and you can measure accordingly.

toDo: I would like a 'Generate Timecard' button on the bottom of main/schedule.

I think we should get started on odometer logic.

Start: Sun 07 Jul 2024 05:26:42 PM CDT

Okay, I have to find a toDo manager which uses a CLI.

Start: Tue 09 Jul 2024 06:36:30 PM CDT

I'm not feeling the main/summary page.

The pdf is not showing trip number on https://cbud.app/main/timecard

I feel like with LLMs you get it done quicker and you get 'functionality' quicker but its like really buggy and you don't know what it is so you have to iron out and the kinks and in that 'ironing' process you might as well should've written out without the LLM.

I still feel like doing it with LLM as described would take just as long but I think I would require less brain power.

Within routes, assocTrucks may not need to be there.

Start: Wed 10 Jul 2024 11:19:03 AM CDT

Side Note: I think like Releases can have the Markdown or similar sort of showing where it looks like a toDo area as such:

"### Branch: timecard-page

  • - 0x0 - Make the timecard functionality work for Enidan. - Link to the PDFs showing the examples.
  • - 0x1 - Show previous timecards
  • - 0x2 - Accept date as Param. - @MonteLogic
  • - 0x2 - Discriminate to only show the org employee which the user is in. - @MonteLogic "

I need to find a way of diagramming my code but it would be like super easy and not take forever like making an Obsidian drawing thing.

Ideally this diagrammer would just take the code repo in as a param and generate a diagram showing how all of the files and functions are linked.

This is a good tool but I don't want to make my repo public.

The extension Sapling is alright but it doesn't really show the functions all that well and it could use more work to get it to where its the desired product for my use case.

I would like for someone to fork Sapling add more function support as well as documenting support, also have functionality where it could be turned into Mermaid files for easy visual diagramming.

I don't think this project would be all that hard it would just be time consuming.

This issue discusses a dependency which is added to a repo but Sapling doesn't need a dependency per se to make it work. This proposed VS Code/Sublime plugin would have all of the proposed features on top of not needing dependencies.

Like I heard Mr. P once say, once React starts to get large it starts to suck, which I totally agree with.

This proposed solution would make it easier to view large projects, and make working large React projects way easier on the brain.

Discussion continued here.

...

Okay, now we are going to make the selector work for timecard and hopefully we can get the selection to persist among different pages within 'main/'.

...

I feel like the enidan-template.ts is more about instating a document versus being related to creating a document with Enidan's stylings.

So we could split the files and then use a any enidan specific logic as a param which will be a function.

We are splitting up generateEnidanPDF.

... 09:34:36 PM CDT

I think I'm going to start working on Leetcode problems and I am going to do them on UserLAnd and try to have them structured as a multi file'real' program rather than a single file program.

Start: Thu 11 Jul 2024 11:58:42 AM CDT

Working on drawing on paper to re-organize the enidan timecard design. Starting to think relying on LLMs for code writing is bad. But learning using LLMs should be alright.

The problem is the file is using hard-coded values and just overall is sloppy code.

03:04:20 PM CDT Added another PDF, this PDF is styled different so have to adjust where the text is at.

I'm going to make it so if there is more than 7 add another sheet and add the 8th value on this 2nd sheet. Doing this after, I move the text to fit the boxes.

... 09:10:25 PM CDT

Working on this:

let trigger = false;
for (const day of daysOfWeek) {
  // Add multiple pages.

  // This is just a duplication of Sunday before it hits Monday.
  // We have to adjust the pages accordingly and it would be fine to just iterate
  // daysOfWeek based on how many days there are and we would just pick the first
  // one which has the earlier date.

  if (day.times.length > 1) {
    console.log(196, trigger);
    const [existingPage] = await pdfDoc.copyPages(pdfDoc, [0]);
    pdfDoc.addPage(existingPage);
  }
  startY = await drawDayWorkTimes(
    page,
    day.times,
    day.name,
    35,
    startY,
    initialRoutes
  );
  console.log(208, trigger);
  trigger = true;
}

Start: Fri 12 Jul 2024 10:23:28 AM CDT

No LLMs for fixing the PDF issue of multiple days. Not using LLMs probably for the rest of the day.

Working on this:

const howManyPagesToGenerate = (daysOfWeek: {
  name: string;
  times: WorkTime[];
}): number => {
  const count = daysOfWeek.times.length;
  return count > 1 ? count : 0;
};

const pagesToGenerate = daysOfWeek.map((day) => howManyPagesToGenerate(day));
const totalPagesToGenerate = Math.max(...pagesToGenerate);

console.log(207, totalPagesToGenerate);

// We make it -1 because one sheet is currently being made.
for (let index = 0; index < totalPagesToGenerate - 1; index++) {
  const [existingPage] = await pdfDoc.copyPages(pdfDoc, [0]);
  pdfDoc.addPage(existingPage);
}

for (const day of daysOfWeek) {
  startY = await drawDayWorkTimes(
    page,
    day.times,
    day.name,
    35,
    startY,
    initialRoutes
  );
}

Okay, so now we got the page number to iterate on we will use this to select the page to write onto the second page.

... 11:38:47 AM CDT

Okay so daysOfWeek will only be 7 nodes in the first dimension.

So we check to see if the first dimension has more than one times node, if so th en we assign it to write on, we would see that it is on the nth node and then pu t that use that nth number to assign to a paper.

scheduleItem:

{
  "id": "97080cbf-ee01-4071-b55e-656033122b0a",
  "dateScheduled": "2024-07-01T16:47:34.680Z",
  "dateAddedToCB": "2024-07-01T16:48:13.385Z",
  "idOfRoute": "clxxojuv70004g6cr7k3jgzze",
  "employeesWorkingInfo": {
    "0": {
      "shiftsWorking": {
        "Morning": true,
        "Afternoon": true
      },
      "selectedEmployeeID": "clva4yl3l0002psjcyd6kelw8",
      "selectedEmployeeName": "DJ Chavours"
    }
  },
  "summary": {},
  "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX"
}

I think this is a good iterator:

    let numberOfMultipleDays = 0;
    for (const day of daysOfWeek) {
      console.log(213, day);

      if (day.times.length > 1) {
        numberOfMultipleDays++;
        startY = await drawDayWorkTimes(
          pdfDoc.getPages()[numberOfMultipleDays],
          day.times,
          day.name,
          35,
          startY,
          initialRoutes,
        );
      }

Writing day.times is wrong because it puts the whole thing in so it should never happen.

This data structure problem is roughing me up. I managed to get Mondays on the second page but the first Page has Mondays and Tuesdays overlapping.

Going to make a JSON file with co-ordinates of the days of the week as they fit on the page.

I think I'm going to with the days of the week regardless of whether there a days worked there.

Then maybe I could make a set which says which ones fit where.

In reality I'm over thinking it as I could just do calculations for which day is later using the Date object as well as just searching through the array but I was/am trying to rely on iteration logic to get me to the finish line.

So I think I'm going to keep on searching the daysOfWeek array instead of self-referencing.

For this: weekDays[i] is a dumb indicator.

// weekDays[i] is a dumb indicator.
const weekDays = Object.keys(coordinates.dayOfWeekLocation);
// The for loop should only be 7 in size, instead of over engineering.
const writeToPDFDaysOfWeek = async (daysOfWeek: daysOfWeekType) => {
  for (let i = 0; i < 6; i++) {
    let j = 0; // Initialize j before the while loop
    while (daysOfWeek[i] !== undefined && j < daysOfWeek[i].times.length) {
      await drawDayWorkTimes(
        pdfDoc.getPages()[j],
        [daysOfWeek[i].times[j]], // Pass a single WorkTime as an array
        weekDays[i],
        returnDaysOfWeekCoordinates(weekDays[i])[0],
        returnDaysOfWeekCoordinates(weekDays[i])[1],
        initialRoutes
      );
      console.log(
        249,
        [daysOfWeek[i].times[j]], // Pass a single WorkTime as an array
        weekDays[i],
        returnDaysOfWeekCoordinates(weekDays[i])[0],
        returnDaysOfWeekCoordinates(weekDays[i])[1]
      );
      j++; // Increment j instead of i
    }
  }
  // comment
};
writeToPDFDaysOfWeek(daysOfWeek);

...08:46:20 PM CDT

Just remembered that you have to create a community to have your product truly succeed.

Start: Sun 14 Jul 2024 11:23:52 AM CDT

That weekDays[i] is a dumb indicator doesn't match the days and only fires randomly.

Why does it fire randomly and how can we make it smarter?

I feel like this doesn't fit the sophistication of the function:

const weekDays = Object.keys(coordinates.dayOfWeekLocation);

... In your code, if you don't know what it is, delete it.

... Sun 14 Jul 2024 05:15:40 PM CDT

For the third param, it's just the weekday which will be written on the PDF. So this is only writing Wednesday on two entries:

await drawDayWorkTimes(
  pdfDoc.getPages()[j],
  [daysOfWeek[i].times[j]], // Pass a single WorkTime as an array
  "Wednesday",
  returnDaysOfWeekCoordinates(weekDays[i])[0],
  returnDaysOfWeekCoordinates(weekDays[i])[1],
  initialRoutes
);

This only produces two entries:

await drawDayWorkTimes(
  pdfDoc.getPages()[j],
  [daysOfWeek[i].times[j]], // Pass a single WorkTime as an array
  "Wednesday",
  72,
  660 - additionTo(),

  initialRoutes
);

But why are there just two entries/WorkTimes being written to the PDF?

I think the problem is co-ordinates.

I need to get the co-ordinates, so I'm going to write a function which takes the workTime object and returns the co-ordinates for the day of the week. Within the input param there will be the dateScheduled field and from there we'll ascertain the date and then get the day of the week from the date and then check it with the co-ordinates which will return the day of the week coordinates for the workTime object.

// We can get the dayName here and get it from 'coordinates.' here rather than below.
for (let i = 0; i < MAX_ENTRIES_PER_DAY; i++) {
  // What even is this?
  // That if statement doesn't make any sense.
  if (i < workTimes.length) {
    await drawWorkTimeInfo(
      page,
      workTimes[i],
      coordinates.startX,
      coordinates.startY,
      routes
    );
  }
}

Not sure if I got those co-ordinates returning and put in the right place cause there all jam packed in on place so to speak.

There all jam packed but I know where they are going just have to return co-ordinates from the function I last committed.

<-----------------------------------------------------------------------------------------------------------> Start: Mon 15 Jul 2024 11:29:08 AM CDT

I wonder what the workflow of writing a large branch of differences where you were figuring stuff out but you want to run a PR of changes which are much more concise.

Okay now, we are going to go thru the PDF and explain what is on the page and how it happened with the console.logs providing perspective.

Okay, so the first page for the weekday slot it is saying:

The first slot says, Monday

The second slot says, Tuesday/Wednesday but these two words are overlapping.

Then this third slot is blank, so, empty.

Then the fourth slot says Thursday.

The fifth slot says, Friday

The sixth slot says, Saturday.

The seventh slot says, Sunday.

Okay, so conjecture these results:

Okay, so this is the code which writes the days of the week:

await drawText(
  page,
  getDayOfWeek(workTimes[0]),
  // I think maybe here we can accurate coordinates.
  returnDaysOfWeekCoordinates(getDayOfWeek(workTimes[0]))[0],
  returnDaysOfWeekCoordinates(getDayOfWeek(workTimes[0]))[1]
);

This is why:

  "dayOfWeekLocation": {
    "Monday": [72, 660],
    "Tuesday": [72, 600],
    "Wednesday": [72, 600],
    "Thursday": [72, 480],
    "Friday": [72, 420],
    "Saturday": [72, 360],
    "Sunday": [72, 300]
  },

Okay, so now that we got weekdays looking good, we are going to focus on writing the rest of workTime.

Which is errantly being done with:

  for (let i = 0; i < MAX_ENTRIES_PER_DAY; i++) {
    if (i < workTimes.length) {
      if (workTimes[i] && workTimes[i] !== undefined) {
        await drawWorkTimeInfo(
          page,
          workTimes[i],
          // I think maybe here we can accurate coordinates.
          coordinates.startX,
          coordinates.startY,
          routes,
        );
      } else {
        console.log('Invalid work time at index', i);
      }
    }
  }`

This would also need to implement down*, because there will be multiple ones of it.

So, I want the date to go down but the rest of the values to stay up.

I want to change these + and - stuff to hard coded values with the JSON file.

So right now it's moving good after I changed the params within drawWorkTimeInfo. This thing is almost done if we don't run into any big problems.

Currently, work the work shifts if there are multiples of them they are on the same line this shouldn't happen, they should be in different rows.

Its starting to not look good after the first one because its too low, so we could get Monday in the correct position and that may fix this problem.

How do we position the first row though?

I think it would have something to do with lineHeight but this variable isn't being used.

... The date string is currently in the bottom right corner.

This statement may change but its sounding confident for now: I need to make the SPACE between the lines bigger no what is being iterated.

Now, what var is controlling the space between workTime entries?

Maybe there is no line height because they are all using hard coded values and the values should just be changed on the appropriate JSON file.

.... Okay, now I am focusing on getting the shifts to iterate over on the shift, 'trip number' column.

For this, workTime[1] is never fired:

const drawDayWorkTimes = async (
  page: PDFPage,
  workTimes: WorkTime[],
  routes: Routes[]
) => {
  getDayOfWeek(workTimes[0]);

  // We can get the dayName here and get it from 'coordinates.' here rather than below.
  await drawText(
    page,
    getDayOfWeek(workTimes[0]),
    // I think maybe here we can accurate coordinates.
    returnDaysOfWeekCoordinates(getDayOfWeek(workTimes[0]))[0],
    returnDaysOfWeekCoordinates(getDayOfWeek(workTimes[0]))[1]
  );
  //
  // This should only be concerned about filling in the workTime info not the day of the week.
  for (let i = 0; i < MAX_ENTRIES_PER_DAY; i++) {
    if (i < workTimes.length) {
      if (workTimes[i] && workTimes[i] !== undefined) {
        await drawWorkTimeInfo(
          page,
          // This may be useless:
          workTimes[i],
          // What is the minus 20 being used for?
          // Move workTime into a more appropriate place.
          returnDaysOfWeekCoordinates(getDayOfWeek(workTimes[0]))[0] -
            coordinates.workTimeSpacingX,
          returnDaysOfWeekCoordinates(getDayOfWeek(workTimes[0]))[1] -
            coordinates.workTimeSpacingY,
          routes
        );
      } else {
        console.log("Invalid work time at index", i);
      }
    }
  }
};

Currently trying to do something so I can put the shifts in the right place because it can be done iteratively.

Here, on line 72, is where the shifts are really showing:

await drawText(
  page,
  workedShifts.join(", "),
  x + coordinates.workedShiftsPositioning.x,
  y + coordinates.workedShiftsPositioning.y
);

Okay, so for the aforementioned code, we can go through ever node within workedShifts as a for loop of 'workedShifts.length' and use drawText within the for loop.

... Okay, so what's next is bring in other values into the PDF besides whats currently on the PDF now, (Mon 15 Jul 2024 06:33:04 PM CDT).

Start: Tue 16 Jul 2024 02:56:44 PM CDT

Getting to work on adding more values into the PDF generation.

Start:

Wed 17 Jul 2024 09:56:56 AM CDT

Move /settings to main/settings

initialRoutes can be null or no data there and there be an error an alert needs to popup saying you need to fill in some data so the error doesn't popup.

Not sure if this is the affected code:

a.href = pdfUrl;
a.download = `employee_times_${initialRoutes[0].routeNiceName.replace(
  /\s+/g,
  "_"
)}.pdf`;
a.click();

But this is the error:

Error generating PDF: TypeError: initialRoutes[0] is undefined
    EnidanTemplatePDF index.ts:30
app-index.js:32:21
    error app-index.js:32
    error hydration-error-info.js:45
    EnidanTemplatePDF index.ts:38

For some reason main/schedule if there is no values there it says not apart of an organization. Still need to make the first use process smoother.

The way this gets to the end of the bus route, is not straightforward and it should be.

The final function should not look like this, he final payload should be the final payload:

export const EnidanTemplatePDF = async (
  workTimeTop: WorkTime[],
  selectedEmployeeID: string,
  selectedEmployeeName: string,
  initialRoutes: Routes[],
  startPayPeriod: string,
  endPayPeriod: string,
) => {
  try {
    const startDate = new Date(startPayPeriod).toISOString().split('T')[0];
    const endDate = new Date(endPayPeriod).toISOString().split('T')[0];

    const modifiedPdfBytes = await generateEnidanPDF(
      workTimeTop,
      selectedEmployeeID,
      selectedEmployeeName,
      startDate,
      endDate,
      initialRoutes,
    );

Need to get rid of org switcher.

For Work Experience that date field needs to be a date and not a string

Having issues with things being undefined when it hits:

let expY = 360;
formData.workExperiences.forEach((exp: WorkExperience) => {
  addText(exp.facilityName, 50, expY);
  addText(exp.employmentDates, 250, expY);
  addText(exp.facilityType, 50, expY - 20);
  addText(exp.unitType, 250, expY - 20);
  addText(exp.cityState, 50, expY - 40);
  addText(exp.position, 250, expY - 40);
  addText(exp.traumaFacility, 50, expY - 60);
  addText(exp.reasonForLeaving, 250, expY - 60);
  expY -= 100;
});

Start: Mon 29 Jul 2024 09:32:14 PM CDT

If I got hired as a client to take on cBud.

I would add a lot more example data points and be able to import from a JSON file so I can iterate and develop faster.

I need beta testers.

I think I'm going to work on cbud and get the features, I was working on, done and I'm going to spend Tuesday and Wednesday doing this.

Then after this, I'm going to look for beta tester who fit the use case.

Also, while I'm working on this, I'm going to get healthcare profiler ready for commercial use.

I would like to get Twilio working with the messages because that'll bridge a big gap.

Manager View, know on main/schedule modal so manager can edit times.

Start: Tue 30 Jul 2024 03:46:41 PM CDT

My focus until vacation is just DOING the process and not getting burnt out.

How can we get this stuff one without winding yourself up?

.... I think I need to look at it from a Remote manager point of view. Like somebody right now is hiring me to run their trucking company and these SaaS functionalities aid in my/our ability to administer the business.

If that's the case I want a clipboard view of every employee and a way to contact them and what their paper work looks like and what their schedule looks like.

I'm trying to figure out why I can't just query clerk for employees and go from there, why do I need an employees table.

I think just creating a user willy-nilly may mess it up because we need fidelity in scheduling.

So, let's query the list of employees from clerk and put that on /employees. ...

Okay, so I think we are going to create a kind of social media profile functionality.

What, I am going to do is make a UI for remote workers to manage the company.

Make schedule functionality for each profile page so people don't have to keep on shifting it on main/schedule.

I'm not going to put any pressure on myself until the start of next week, August 5th.

Start: Wed 31 Jul 2024 03:20:37 PM CDT

Create localized view of schedule on every user's profile.

How does the schedule component work?

Okay, so I think there is going to be a "board" of all the features offered and on the board will be an explanation of how each feature works.

I guess I could host an HTML file, say on MonteLogic.com

Ideally it would HTML with JSON and you wouldn't have to build, you can just run it like an html file.

I'm working on generating HTML pages in Next.js 13 and it looks like I need to do something like:

import prisma from "#/lib/prismadb";

export async function generateStaticParams() {
  const routes = await prisma.routes.findMany();
  return routes.map((route) => ({
    routeId: route.id,
  }));
}

export default async function RoutePage({
  params,
}: {
  params: { routeId: string };
}) {
  const { routeId } = params;
  const route = await prisma.routes.findUnique({
    where: { id: routeId },
  });

  if (!route) {
    return <div>Route not found</div>;
  }

  return (
    <div>
      <h1>Route Details</h1>
      <p>Route ID: {route.id}</p>
      {/* Add more route details here */}
    </div>
  );
}

Instead of creating an API file like:

// app/api/routes/[routeId]/route.ts

import { NextRequest, NextResponse } from "next/server";
import prisma from "#/lib/prismadb";

export async function DELETE(
  request: NextRequest,
  { params }: { params: { routeId: string } }
) {
  const { routeId } = params;
  try {
    await prisma.routes.delete({
      where: {
        id: routeId,
      },
    });
    return NextResponse.json(
      { message: "Route deleted successfully" },
      { status: 200 }
    );
  } catch (error) {
    console.error("Error deleting route:", error);
    return NextResponse.json(
      { error: "Failed to delete route" },
      { status: 500 }
    );
  }
}

We really need to figure out a way to get the database queries DOWN! Resort to JSON file maybe. ... Okay, so we need tabs over the employee page here as well just as for main/

It shows no matter what, so I think that there should be a warning which says ID does not exist or something like this.

Start:

Thu 01 Aug 2024 01:23:05 PM CDT

Okay, so we have to set up the tabs but it needs to be at the bottom.

Also, we have to have a edit profile functionality. ... Okay, there is going to be a 'My Profile' link which everyone is going to have and then there is going to be an Employees page which only mods, managers and admins have.

Start:

Fri 02 Aug 2024 06:49:14 PM CDT

I would like to add a background to the 'My Profile' Page similar to the background to the data details.

Also, if it is the employee viewing it, would like for it to be 'My Profile' but if a mod is viewing it then it'll be 'Employee X Profile'. Or we can just make it the name of the Employee and append Profile and that'll be the one for everyone.

Everyone has a My Profile page.

Mods and ups can view Employees page and view every employees profile along with other details.

For the profile page, there should be a 'Request Route' function rather than an 'Add Route' function at the bottom.

I would like for there to be more of the slide showing but we need to get the core logic done which is editing the schedule and generating timecards. Select a template should only be available for admins, once a template is selected once then that will be the default template for all employees.

Okay, so right now, the user doesn't exist and we aren't getting any errors.

What is the pairing mechanism ?

I think when a user/employee joins an org, they should be shown a screen with the available names, like hey are you this person we created.

Also, for each employee, there can be an invite and they would be invited via clerk and the clerkID pairing could be recorded this way.

Okay, so in the employee section it'll be like a different color and then it'll like in the employee area, this user hasn't not setup an account, invite this person.

I think I'll make it that if there is no name it'll be the name before the @ symbol in the email.

I'm not all of that of a fan of the org dropdown in the middle of the screen. I think such settings should be hidden away in /settings.

In order to get core logic done we need to tie it together with Clerk stuff so we know we are getting a good ID.

Why do we need to tie clerk with it and include clerk id?

  • It prevents duplicates and allows for better invitation logic.
  • The user needs this as an anchor to base actions.

We will use id rather than employeeId. Still don't know why employeeId is still there.

... So it looks like we are going to have a page which says invitations, previous invitations as as well as sent invitations, etc.

Start: Sun 04 Aug 2024 11:16:33 AM CDT

Okay, so we have to get an invite status page going. Start:

Sun 18 Aug 2024 02:51:56 AM CDT

Okay, need to write down features better and faster which is why a CLI could be dope but we got side tracked in note taking CLIs.

But feature, Profile page with all that and the admin view.

Let's make a blog sort of thing, because we can write a lot and drive traffic for free on this topic.

Start:

Sun 18 Aug 2024 02:20:55 PM CDT

I would like to get a summary view of homepage.

Add this to your settings.json file to check for all of the TypeScript errors: "typescript.tsserver.experimental.enableProjectDiagnostics": true,

Start:

Mon Aug 19 2024 16:24:31 CDT

I would like for it to redirect to /home if the user is signed in.

This project has ballooned to the point where I forget my toDos also, it is messy and takes to long to add onto.

So looking at todo command lines: https://github.com/yuler/gh-todo

Okay, I'm not using those command lines we are using the gh command line from GitHub and just accessing the issues from this CLI.


Tid Bit:

I think this is a dope drop down: https://montelogic.com/wp-content/uploads/2024/08/Screenshot-2024-08-19-at-17-46-04-PNG-to-SVG-Online-Image-Vectorizer-Convert-JPG-PNG-images-to-SVG.png


In the naming convention we need to put the iteration number as well as the date.


Okay, so our Planetscale instance was frozen so working on other things.

Start:

Tue Aug 20 2024 17:44:25 CDT

Switching to Turso rather than Planetscale because Planetscale is boo boo.

...

Looking at these API files, just found out that these api files are not it, we should prioritize RSCs.

We have to replace where Json type was at when we use MySQL.

We need to fill every initialRoutes, with filled data.

Side Bit: I think if we have dummy data then we are going to need fast forward the dates on the JSON file.

This app is going to be super broken for a good minute.

Start:

Thu Aug 22 2024 11:57:45 CDT

I would like to simplify cbud because these operations are too complicated.

Alright, so I got ride of prisma all together and replaced with Drizzle but I'm pretty sure, cbud is very broken right now.

....

let's add dummy data or invitation to seek out other companies.

Side note: Cannot fully develop locally because clerk data brought in via API.

"Seems empty, lets add Example data to get you started.

And then we will just add one route to it with example data.

Added the JSON file, the hope is to read from the JSON file directly.

I added the file but really what we need is to deploy to Vercel with no errors.

[+] Add analytics

Start:

Aug 24 2024 14:13:07 -03

Going to merge "issue/59" even though it's a broken Pull Request.

Start:

Sun Aug 25 2024 14:59:02 -03

Working on '/main/schedule' now.

Now we can create employees we need to get them to the DOM as well as the Routes.

Start:

Tue Aug 27 2024 19:25:45 -03

Working on /main/schedule

Okay, so the dropdown, needs to match, also we need to get the values which are added from Add Employee

So, lets get those names onto the view.

main/schedule and /employees

What is clerkID on Employees table, it should be 'clerkOrgID'

Let's get rid of the Employees table and just add Employee via the add member method: https://clerk.com/docs/references/javascript/organization/members

If there is too many members, then we will tell the client they have uncoupled members.

"Remember that users need to be registered with Clerk before they can be added to an organization. You might want to consider adding a separate flow for inviting new users to register if they're not already in your Clerk user base."

So we need add invitation logic to decoupled members. Then once they are invited then we change it.... or not.

Can't add employees. Just realized today was a waste, because of invites.

Start:

Thu Aug 29 2024 17:14:49 -03

Got rid of employeeId going to use id, for reference instead and then clerkId is going to be empty, when its paired up thats when we will associate the clerk around by tying the clerkId.

I still need to show the rest of the component and not just the invitation component and show the scheduling made.

Start:

Fri Aug 30 2024 09:00:00 -03

Alright, lets get this invitation stuff dope.

Got authorization segregation to work, now we need to invite users.

https://clerk.com/docs/organizations/inviting-users

Currently the list is showing all of the invitations but not the one related to the id, so we need ot fix that and then it should be done, then PDF then documentation, the release.

Okay, if you sign up, it doesn't onboard you it just sends you to / with an account on the org.

[+] Need sign in component to replace org switcher when logged out.

We could just ask the user to pair with an account which doesn't have data.

Also, if we send an invitation we need to mark that invitation as to one person.

Start:

Aug 31 2024 15:28:11 -03

Okay, so if there is an account we will show the outstanding account which is matched with their email.

Then have to get manager view working and employee view.

Current state of the invite to data system?

Currently you just sign in and you are part of the organization without any onboarding.

This all URLs thing where they do stuff for 'sign-up/some-url', I'm not seeing it.

You can implement these session tokens: https://youtu.be/lWcDAxNpJI8?si=Y8bpyRvvyrdX-c3U&t=1218

But it looks like this session stuff is accessed on the server.

"

Recording: " It's just like, you just sign in And they just have like, they're just like a part of the organization, But I try to like, make this sign up thing like pointed to, like people, but it doesn't work. Look at all, Like it just it just signs them up, but it doesn't take them to the onboarding screen.

So we need like an onboarding screen type of thing Because it's just not pointing to it With and if it and we need like high Fidelity Cuz we need to like, point to that stuff. We need, we need to, we need to, like, Not have duplicate accounts. We need to be like onboarding onboarding screen.

Now, there should be like an alert or at least the modal whenever they first sign up. Like, Like redirected, like redirecting them to that, or something like that. Or like It's like multiple, like Like Thing small systems to follow back on where you're like,

We want to get your onboard. Anyways, We're going to go like we we're gonna get you on board.

"

The metadata approach is something we can try.

...

There are going to be three categories,

  • Clerk user but not in the database

  • In the database but not a Clerk user, (someone made data for them)

  • In the database and a Clerk user.

Make a /onboarding page

We can take some params of the URL and build stuff upon it:

Custom redirect URL

When creating an organization invitation and using Clerk's Next.js, Remix, or Backend SDKs, you can specify a custom redirect URL. After users click on organization invitation link and the ticket is verified, they will get redirected to that URL. The URL will contain two important query parameters added by Clerk: **clerk_ticket and **clerk_status.

The __clerk_ticket query parameter will hold the actual ticket token, which can be used during sign-in and sign-up flows in order to complete the organization invitation flow.

The __clerk_status query parameter is the outcome of the ticket verification and will contain one of three values:

sign_in indicates the user already exists in your application. You should create a sign-in ticket in order to complete the flow.
sign_up indicates the user doesn't already exist in your application. You should create a sign-up ticket in order to complete the flow.
complete indicates the user already exists in your application, and was signed in. The flow has been completed and no further actions are required.

An example implementation on how to create an invitation by providing a redirect url using the JavaScript Backend SDK:


I like, this solution where you input your uuid into the metadata.

Let's try to rework this solution but with the invitation logic.

This is a helpful project but it doesn't use a local database.

...

So we are going to send an invitation which will fill the user metadata with the UUID if that still doesn't work, we need a backup check for the UUID not working but this backup could be /onboarding. /onboarding will take tare of errant invitations and users just showing up to the site.

On /onboarding they will be presented with the unmatched data employees and a special focus will be given to records with the same email.

If they don't have an email we could use phone number. But we do need a phone number field because of automated messaging.

So we need to have an email field on the employees table.

say they just went on cbud.app and got an account, then we will redirect to '/onboarding'.

Honestly, I think the onboarding thing would be better all around, so lets do that first and then work on adding metadata to a user via an invitation when we can add the uuid to a user's metadata on /onboarding.


Side Note: I don't think a Next.js coding in general would be good, I would much rather focus on edge cases which don't have a solution I don't think these things are enough for ebooks.

But an eBook on libsql would be dope, also, an eBook on ORMs would be dope.

Also, I think an eBook on making the Gutenberg/WordPress development process better and more in line with the DX or Remix or Next.js.

Using better JS with the Gutenberg stuff: https://www.youtube.com/watch?v=tj5VW2xJsqU&list=PL6dZTR-Ez9JBjeH4geYZ4hNnKyPBIywEX&index=81

__ In here we could propose a shift from php to RSCs.


With this, what is the point of env.local and using some sign-up URL. https://gist.github.com/MonteLogic/b9fbc1be10a74cfbe48632f8f034e320

Start:

Sun Sep 01 2024 13:11:10 -03

Making a full page can be hard, so we are just going to redo the menu so it says onboarding and we have time we can work on a full screen functionality for this.

Also, there may not need to be onboarding but onboarding can be a tutorial.

So if they don't have an email which has already been associated with pre-filled out data, then no real need for onboarding besides a tutorial.

Or we can just leave it as is and do the association logic which is the tough part.

Okay, so onboarding it'll say your email and/or your name and it'll show the records which have your name and/or your email.

We are doing this via customizing the session token.

This is how you type sessionClaims stuff: https://gist.github.com/MonteLogic/03515da82060e578597a38872545dc55

Okay, so now we got the email we need to search the db for the record which has this email associated with it.

Start:

Mon Sep 02 2024 12:47:53 -03

Okay, so now that we got the session token working good, what we need to do now is find the matching records in the database.

For the pairing mechanism:

Onclick add the current user's email to the local db and add the local db id to their clerk account.

Currently the email is not being written on up.

Currently on '/employees' nothing is paired because it needs to because their likeness needs to be edited on '/schedule'

I want more information to be showed for the employee selected as well as being able to edit their email as well as go on their profile page for editing.

How do we know its paired all the way? - Key Point ; issue 67

  • The localdb record will have a clerkID, and an email.
  • The metadata in Clerk will have the localdb id. What event can we hook into so we can send the localdb id to Clerk metadata?

Side Note:

If clerk had the logic in it to pre add data this wouldn't be needed. But we are doing this because currently there's only adding data via invitation and that's just invitation, not when a user signs up on his own.


Start:

Tue Sep 03 2024 10:16:35 -03

Flowcharts can include links: flowchart LR A-->B B-->C C-->D click A callback "Tooltip for a callback" click B "https://www.github.com" "This is a tooltip for a link" click C call callback() "Tooltip for a callback" click D href "https://www.github.com" "This is a tooltip for a link"

This chart is better: flowchart TD node1["Never written code"] --> node2["Written basic code"] node2 --> node3["Written useful code"] node3 --> node4["Created useful project"] node4 --> node5["Project useful to clients"]

node1 --> node6["Learned from podcasts"]
node6 --> node3

node2 --> node7["Practiced syntax"]
node7 --> node3

node3 --> node8["Explored tech stack"]
node8 --> node4

click node1 callback "Tooltip for a callback"
click node2 "https://www.github.com" "This is a tooltip for a link"
click node3 call callback() "Tooltip for a callback"
click node4 href "https://www.github.com" "This is a tooltip for a link"

Good Stackoverflow answer: https://stackoverflow.com/a/71167934/10742834

Ideally we will be able to write a script which makes it so that it can be written into mermaid script and outputted.

I like the way this diagram looks:

classDiagram
    class FeatureBoard {
        +schedulingViaSlider(45)
        +userProfiles(32)
        +clerkAuth(17)
    }

    class SchedulingNode {
        +schedule()
    }

    class UserProfileNode {
        +profile()
        +settings()
    }

    class ClerkAuthNode {
        +login()
        +signup()
        +logout()
    }

    FeatureBoard --|> SchedulingNode :  "45"
    FeatureBoard --|> UserProfileNode :  "32"
    FeatureBoard --|> ClerkAuthNode :  "17"
Loading

Issue 67:

Looking at this post for refining syncing logic: https://stackoverflow.com/questions/76844758/next-js-with-clerk-auth-how-to-detect-if-a-user-just-signed-up

So going to add a check on /onboarding and '/' it'll check if the clerk user has a record with a clerk id.

I will also, add the localdb id to the user's meta data on clerk.

This is an idempotent operation so we should the fidelity rate should be high.

If clerkid and email are both filled then we now its paired up.

I feel like if they create a user for scheduling purposes, the list should look better and have the email on it and when a user is created there should be an email field.

Also, there could be a functionality for pairing existing data...

But we NEED to get market soon so, I think the use of just having a user click on a record

Okay, so when a user is onboarded they will view all of the outstanding records and if there isn't there's then when they click no then a record will automatically be created.

This button on /onboarding will always be available as long as the user isn't paired.

Start:

Wed Sep 04 2024 12:36:53 -03

[] Add button which says, do not see own record

[] Rework timecard so it is good and usable.

Login via an unpaired account and add record by client.

But this is clerk so, we need to add a record. Because it shouldn't show records if there is no record in Employees.

On /employees it shows me highlighted for two emails when it should only be for my own, which is the one which is logged in.

I will work on employees/[id] because it needs to work but before that we need to get /onboarding dope.

So click on unpaired Employees on /onboaring and pair but I could make it a modal but that'll take a lot of time, I'd rather them just click on the profile and pair it. If the employee is already paired then there shouldn't be an invite thing

Okay, so right now, its being paired even though it shouldn't be.

So, a record is being created automatically. It should only be created after the user looks through the employees.

Add login thing for unsigned in users.

Okay, so for EMP users we have to be able to write their email name.

Okay, so what I think would be better is that every major version is when we change the production domain.

Start:

Thu Sep 05 2024 14:48:44 -03

If a member is already paired don't include invitation div #73

For some reason, on my own profile its showing two things(components).

No invite issues now, now we need: different auth views, fix pdf, stripe setup docs

Lets fix the pdf as well as check we can even make accurate PDFs.

Okay, so when an employee is on their profile, it's almost if they are receiving the same view as the team schedule as far as editing.

So when a route is added the shifts aren't showing!

[] Make it gold when the shift is occupied and the employee selected should stay in focus.

[] Transfer in the domain into Vercel.

Okay so Profile is whack, so we are going to make it good then work on timecard generation from there. We

Start:

Fri Sep 06 2024 08:26:09 -03

Profile is whack, we need to replace Add Route with Request to Join Route.

Bell Notifications?

When a modification is made on Team Schedule it doesn't show up on their profile.

When a modification is made it should show up on their profile without a request, it should just show.

Working on: ui/timecard/slider-component-for-user.tsx

Now, we gotta redo SliderComponentForUser

Yes, so there would be another action when a schedule is set for team schedule for a user which hasn't been authorized for a route.

We can do this mechanism later, and just do eligible routes.

Or do eligible routes later.

For employee auth level we can use this.

If I add eligibleRoutes then we'll also need a mechanism for adding routes to this column.

ITs good enough

[] Add a saving... state for modal thing [] Also summary is broken.

Now we got: Parsed employeesWorkingInfo is not an array:

Okay, so the WorkTime has some kinks to it.

First of all the date scheduled is in Integer form when it should be in date form.

[] Fix pdf [] add auth roles

Start:

Sep 07 2024 06:38:21 -03

[] Fix pdf

Question: What is the current state of the PDF being generated?

Don't know why there are all these days of the week there. Also 'null null for the name'

Why is name not showing up on the profile? employees/[id]

Right now for the local database, its all out of whack.

It doesn't matter about getting the name because its very inaccurate.

For some reason the WorkTime record is being created via the clerk id. Maybe if I added the name as well to the WorkTime record it would be dope.

It is already being added but its taking in the clerk value.

Let's change the name on the profile from NULL NULL to whats on the local db which should have a name.

Still don't know how the duplication can be good so we are going to just write the name on the profile page and that'll send up to clerk.

I think there can be a button which says "sync db" and that'll send all the relevant metadata up to Clerk.

Let's lean into using Clerk more for the description of the user.

New Paradigm:

Also, once a pairing is made, we will rely on Clerk for the naming information of the user and only WorkTime and Payment settings will be located on the db.

Maybe we could do a 'sync db' button which would then transfer the main data to clerk.

Now that the PDF generation is 'okay' we can start to work on design.

Start:

Mon Sep 09 2024 09:41:49 -03

The name isn't written in a way which becomes stale but you do need to refresh the page after editing the name.

We are going to get rid of the days of the week on the PDF.

[] Get the colors back to normal. Change it by the end of the day.

Monday IS the first day of the week and Sunday is the last day of the week.

We need to find out a way for tab state to persist.

UGH!

The slider just broke and now its not saving anything. Need to fix the slider as well as make it yellow so we can detect this stuff earlier.

Side Note: We should write the slider as one component and just pass in props to determine the user slider.

LLMs are NOT working to get the yellow thing to function. Also, I would like to put the test db in a sqlite file for the testing the changing of the sliders.

Okay, so the dateScheduled thing is mad whack, so we need to switch it to a date which can be read and evaluated in the slider.

Okay, so we are changing the object to include the workDate so we don't have to search up the db to find the work date thus evaulating if its yellow or not will be much more simple.

interface EmployeeShiftInfo {
  selectedEmployeeID: string;
  selectedEmployeeName: string;
  shiftsWorking: Record<string, boolean>;
  workDate: string;
}

Tomorrow:

Okay so tomorrow what I want to do is I would like to get those test set up for sqlite

Get the last response for Claude where it's talking about making it go up gold and refine that.

Then go back to the PDF stuff and then I know that I haven't figured out the pages on the contractor Bud site but I do know for the last project I worked with I figured out how to make multiple pages based on certain data..

Start:

Tue Sep 10 2024 18:47:22 -03

Make SliderComponent, one component.

Got the slider to show past stuff and what not but it's surprised on the current date.

Okay, we are going to make SliderComponent one component and then we are going to test it with sqlite.

So, I think the component should have a current day param so its easier to test, rather than instating the date in the middle of the component.

Working on making the pdf good.

Currently if there is a date out of the first week period, 15 day period a second page isn't made it should, we will correct this after we fix the coordinate system.

Start:

Wed Sep 11 2024 08:35:43 -03

Side Note: Stop today at 16:00

Alright, working on the PDF making it look good on the first page and then we'll work on making multiple pages based on the data.

Okay, so Tuesday and Date slot looks decent. The trip number can be shifted down, we also don't have the start time or end time there.

Alright, let's bring the start time in.

We have two components for generating timecards they should only be one with just another added param*.

This is what workTimeTop looks like:

workTimeTop:

[
  {
    "id": "",
    "dateScheduled": "2024-09-06T22:44:52.027Z",
    "dateAddedToCB": "1725921966928.0",
    "idOfRoute": "c33f5569-714f-487b-b73b-c85c8225f8ea",
    "employeesWorkingInfo": "{\"user_2eeGhzLxDLApONQemmF4SjN4BC4\":{\"selectedEmployeeID\":\"user_2eeGhzLxDLApONQemmF4SjN4BC4\",\"selectedEmployeeName\":\"Dennis\",\"shiftsWorking\":{\"Morning\":true,\"Afternoon\":true},\"workDate\":\"2024-09-06T22:44:52.027Z\"}}",
    "summary": "{}",
    "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX"
  },
  {
    "id": "c33f5569-714f-487b-b73b-c85c8225f8ea_2024-09-05T22:48:35.459Z",
    "dateScheduled": "2024-09-05T22:48:35.459Z",
    "dateAddedToCB": "1725922124132.0",
    "idOfRoute": "c33f5569-714f-487b-b73b-c85c8225f8ea",
    "employeesWorkingInfo": "{\"user_2eeGhzLxDLApONQemmF4SjN4BC4\":{\"selectedEmployeeID\":\"user_2eeGhzLxDLApONQemmF4SjN4BC4\",\"selectedEmployeeName\":\"Dennis\",\"shiftsWorking\":{\"Morning\":true,\"Afternoon\":true},\"workDate\":\"2024-09-05T22:48:35.459Z\"}}",
    "summary": "{}",
    "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX"
  },
  {
    "id": "c33f5569-714f-487b-b73b-c85c8225f8ea_2024-09-10T22:48:47.978Z",
    "dateScheduled": "2024-09-10T22:48:47.978Z",
    "dateAddedToCB": "1725922138292.0",
    "idOfRoute": "c33f5569-714f-487b-b73b-c85c8225f8ea",
    "employeesWorkingInfo": "{\"user_2eeGhzLxDLApONQemmF4SjN4BC4\":{\"selectedEmployeeID\":\"user_2eeGhzLxDLApONQemmF4SjN4BC4\",\"selectedEmployeeName\":\"Dennis\",\"shiftsWorking\":{\"Morning\":true,\"Afternoon\":true},\"workDate\":\"2024-09-10T22:48:47.978Z\"}}",
    "summary": "{}",
    "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX"
  },
  {
    "id": "c33f5569-714f-487b-b73b-c85c8225f8ea_2024-09-11T22:03:37.646Z",
    "dateScheduled": "2024-09-11T22:03:37.646Z",
    "dateAddedToCB": "1726005831908.0",
    "idOfRoute": "c33f5569-714f-487b-b73b-c85c8225f8ea",
    "employeesWorkingInfo": "{\"user_2eeGhzLxDLApONQemmF4SjN4BC4\":{\"selectedEmployeeID\":\"user_2eeGhzLxDLApONQemmF4SjN4BC4\",\"selectedEmployeeName\":\"Dennis\",\"shiftsWorking\":{\"Morning\":true,\"Afternoon\":true},\"workDate\":\"2024-09-11T22:03:37.646Z\"}}",
    "summary": "{}",
    "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX"
  },
  {
    "id": "c33f5569-714f-487b-b73b-c85c8225f8ea_2024-09-18T01:06:28.852Z",
    "dateScheduled": "2024-09-18T01:06:28.852Z",
    "dateAddedToCB": "1726016806921.0",
    "idOfRoute": "c33f5569-714f-487b-b73b-c85c8225f8ea",
    "employeesWorkingInfo": "{\"user_2eeGhzLxDLApONQemmF4SjN4BC4\":{\"selectedEmployeeID\":\"user_2eeGhzLxDLApONQemmF4SjN4BC4\",\"selectedEmployeeName\":\"D Chavours\",\"shiftsWorking\":{\"Morning\":true,\"Afternoon\":true},\"workDate\":\"2024-09-18T01:06:28.852Z\"}}",
    "summary": "{}",
    "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX"
  }
]

I am going to add the times of the shifts working so we don't have to do extra searches up the db to find out the times.

employeesWorkingInfo: {"user_2eeGhzLxDLApONQemmF4SjN4BC4":{"selectedEmployeeID":"user_2eeGhzLxDLApONQemmF4SjN4BC4","selectedEmployeeName":"Dennis","shiftsWorking":{"Morning":true,"Afternoon":true},"workDate":"2024-09-06T22:44:52.027Z"}}

Changing it to look like this:

{
  "user_2eeGhzLxDLApONQemmF4SjN4BC4": {
    "selectedEmployeeID": "user_2eeGhzLxDLApONQemmF4SjN4BC4",
    "selectedEmployeeName": "Dennis",
    "shiftsWorking": {
      "Morning": [true, [500, 800]],
      "Afternoon": [true, [1500, 1900]]
    },
    "workDate": "2024-09-06T22:44:52.027Z"
  }
}

Aside:

The name for the user isn't updating, on the employees page for some reason. Currently, its only changing the name OF my name (d**@gmail.com) rather than changing the name of the employee which profile I am on.

Slider Component:

Dilly dallying with the modal switches now that I got that working back to writing the PDF.

We are going to take the times

Aside: We could have a custom feature where you can export as a writable spreadsheet and if needed we can have our own PDF editor within the app.

The colors are messed up now but when we fix it, it'll be much more precise and we won't have the flickering issue.

Working on this file: ui/employees/employee-based/for-employee-timecard-component.tsx

For employee means there is a duplicate so I would like to get rid of that.

Times are being printed out in the PDF but is not writing times in the modal

Aside: These objects suck.

We need to figure out a better way of working with objects and typing objects within the setState.

Back to working on writing in the modal.

Writing the shift times to workTimeEmployee

console.log(197, shiftSlots);
197 [{"name":"Morning","startTime":"05:00","endTime":"08:00"},{"name":"Afternoon","startTime":"15:01","endTime":"19:00"}]

For ModalSwitches we have to locate shiftSlots time and put it where it belongs in the object:

Start:

Sat Sep 14 2024 19:56:46 -03

So the times are coming out for the last shift but not for the others also the name of the shifts isn't coming out.`

Today is Shabbos so we don't work on Shabbos and take it easy. So tomorrow we are going to fix the PDF.

I just learned that you should avoid complex objects, thanks WordPress(sarcastic).

So, I could not normalize it then I would have to deal with maintaining the complex object but I would release it quicker.

But nah, lets normalize it.

Normalizing the db

Sun Sep 15 2024 10:35:40 -03

Today we are normalizing the db.

This is what my 2NF database looks like, not sure if the referencing of employee.id will work entirely as a lot of the db will be shared with the Clerk db:

import { sql } from "drizzle-orm";
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";

// Helper function for UUID generation (to be implemented in your application code)
const generateUUID = sql`(lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-4' || substr(lower(hex(randomblob(2))),2) || '-' || substr('89ab',abs(random()) % 4 + 1, 1) || substr(lower(hex(randomblob(2))),2) || '-' || lower(hex(randomblob(6))))`;

export const employees = sqliteTable("Employees", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  clerkID: text("clerkID").default(""),
  organizationID: text("organizationID").notNull(),
  employeeName: text("employeeName").notNull(),
  email: text("email").notNull().default(""),
  phone: text("phone").notNull().default(""),
  dateScheduled: text("dateScheduled").default(sql`(datetime('now'))`),
  dateAddedToCB: text("dateAddedToCB").default(sql`(datetime('now'))`),
  img: text("img").default(""),
});

export const employeeEligibleRoutes = sqliteTable("EmployeeEligibleRoutes", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  employeeId: text("employeeId")
    .notNull()
    .references(() => employees.id),
  routeId: text("routeId")
    .notNull()
    .references(() => routes.id),
  organizationID: text("organizationID").notNull(),
});

export const incomingTexts = sqliteTable("IncomingTexts", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  dateSent: text("dateSent").notNull(),
  dateTimeOfGasBuying: text("dateTimeOfGasBuying").notNull(),
  amtOfGasPurchased: text("amtOfGasPurchased").notNull(),
  gasTankAfterFilling: text("gasTankAfterFilling").notNull(),
  dateAddedToCB: integer("dateAddedToCB").default(sql`CURRENT_TIMESTAMP`),
  from: text("from").notNull(),
  body: text("body").notNull(),
  mediaUrl: text("mediaUrl").notNull(),
  img: text("img").default(""),
  truckId: text("truckId").references(() => trucks.id),
});

export const receipts = sqliteTable("Receipts", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  dateSent: text("dateSent").notNull(),
  dateOfPurchase: text("dateOfPurchase").notNull(),
  employeeId: text("employeeId")
    .notNull()
    .references(() => employees.id),
  typeOfPurchase: text("typeOfPurchase").notNull(),
  amtPurchased: integer("amtPurchased").notNull(),
  gasTankAfterFilling: text("gasTankAfterFilling"),
  dateAddedToCB: integer("dateAddedToCB").default(sql`CURRENT_TIMESTAMP`),
  routeId: text("routeId")
    .notNull()
    .references(() => routes.id),
  vehicleId: text("vehicleId")
    .notNull()
    .references(() => trucks.id),
  img: text("img").default(""),
});

export const routes = sqliteTable("Routes", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  routeNiceName: text("routeNiceName").notNull(),
  routeIDFromPostOffice: text("routeIDFromPostOffice").notNull(),
  dateRouteAcquired: integer("dateRouteAcquired").default(
    sql`CURRENT_TIMESTAMP`
  ),
  dateAddedToCB: integer("dateAddedToCB").default(sql`CURRENT_TIMESTAMP`),
  img: text("img").default(""),
});

export const routeCurrentTruck = sqliteTable("RouteCurrentTruck", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  routeId: text("routeId")
    .notNull()
    .references(() => routes.id),
  truckId: text("truckId")
    .notNull()
    .references(() => trucks.id),
  dateAssigned: text("dateAssigned").default(sql`(datetime('now'))`),
});

export const routeAssociatedTrucks = sqliteTable("RouteAssociatedTrucks", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  routeId: text("routeId")
    .notNull()
    .references(() => routes.id),
  truckId: text("truckId")
    .notNull()
    .references(() => trucks.id),
});

export const routeAllocatedShifts = sqliteTable("RouteAllocatedShifts", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  routeId: text("routeId")
    .notNull()
    .references(() => routes.id),
  shiftDate: text("shiftDate").notNull(),
  shiftDetails: text("shiftDetails").notNull(),
});

export const stripeCustomer = sqliteTable("StripeCustomer", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  userId: text("userId").unique().notNull(),
  stripeCustomerId: text("stripeCustomerId").unique().notNull(),
  createdAt: integer("createdAt").default(sql`CURRENT_TIMESTAMP`),
  updatedAt: integer("updatedAt").default(sql`CURRENT_TIMESTAMP`),
});

export const transactions = sqliteTable("Transactions", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  amt: integer("amt").notNull(),
  num: integer("num").notNull(),
  payee: text("payee").notNull(),
  category: text("category").notNull(),
  dateAddedToCB: integer("dateAddedToCB").default(sql`CURRENT_TIMESTAMP`),
  dateOfPurchase: text("dateOfPurchase").notNull(),
  memo: text("memo").notNull(),
  c: text("c").notNull(),
  balance: integer("balance").notNull(),
});

export const trucks = sqliteTable("Trucks", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  truckNiceName: text("truckNiceName").notNull(),
  dateAddedToCB: integer("dateAddedToCB").default(sql`CURRENT_TIMESTAMP`),
  vinNumberOfTruck: text("vinNumberOfTruck").notNull(),
  truckMake: text("truckMake").notNull(),
  currentAmtOfGas: text("currentAmtOfGas").default("0"),
  img: text("img").default(""),
});

export const workTime = sqliteTable("WorkTime", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  dateScheduled: text("dateScheduled")
    .notNull()
    .default(sql`(datetime('now'))`),
  dateAddedToCB: text("dateAddedToCB")
    .notNull()
    .default(sql`(datetime('now'))`),
  routeId: text("routeId")
    .notNull()
    .references(() => routes.id),
  summary: text("summary").default("{}"),
});

export const employeeWorkTime = sqliteTable("EmployeeWorkTime", {
  id: text("id")
    .primaryKey()
    .default(sql`${generateUUID}`),
  organizationID: text("organizationID").notNull(),
  workTimeId: text("workTimeId")
    .notNull()
    .references(() => workTime.id),
  employeeId: text("employeeId")
    .notNull()
    .references(() => employees.id),
  workInfo: text("workInfo").notNull(),
});

I think the organizationID will be employee.id until an org is created then I guess it'll change.

We are trying to store this info as a table rather than an non-key attribute:

This was employeesWorkingInfo:

{
  "user_2eslQao0IQMnQuDyNp8bUxzuqMI": {
    "selectedEmployeeID": "user_2eslQao0IQMnQuDyNp8bUxzuqMI",
    "selectedEmployeeName": "null null",
    "shiftsWorking": {
      "Morning": [true, ["05:00", "08:00"]],
      "Afternoon": [true, ["15:01", "19:00"]]
    },
    "workDate": "2024-09-13T20:57:32.003Z"
  }
}

routeShiftInfo table

Here will be:

For routeShiftInfo:

One row: { "name": "Morning", "startTime": "05:00", "endTime": "08:00", "routeId": 'c33f5569-714f-487b-b73b-c85c8225f8ea', "organizationId": 'org_2i7M3akTfu1kPCwu4DdHXS4rYL0'

} Second row: { "name": "Afternoon", "startTime": "15:01", "endTime": "19:00", "routeId": 'c33f5569-714f-487b-b73b-c85c8225f8ea', "organizationId": 'org_4235fsd5ahg'

}

routeId attribute description: routeId: text('routeId') .notNull() .references(() => routes.id),

Organizations share users within their systems so we must keep organizationID as a discriminating attribute.

Screw viewing past reference times, just query the current route data.

This is a lot of work with showing past information and I'm not entirely sure we are going to need to do this.

We could just have a lookup table, and have it be at a certain time it was this, if need be for past references, viz. when and what the times and names of the shifts were for the route.

This will also make it normalized and reduce redundant data.

Saving Generated Timecards

If we save generated time card data that may fix the issue of users wanting to look up past data and it not being there.

Normalizing

So we are not worrying about saving values in the past we are just going to look up the times within the routes or relevant tables.

Multiple sources of truth

Now, is the clerk, userID accounted for...

Deleted extra tables

Don't needs stripe info because its just clerk metadata. Clerk account, we bill with Stripe.

Start:

Mon Sep 16 2024 08:29:25 CDT

I would like to get a prod table so when I alter the table prod doesn't break.

So we need to get a prod database up.

Setting up multiple dbs in Turso

So we have a db named: prod-database-contractor-bud-1

Okay, so I have two dbs but the schema is in the past so, I need to run the schema.ts file on there which was there at the time of the Pull Request.

Okay, I added a prod db and added the credentials to the Vercel project.

Suite of Tests

We need a suite of tests to run on PR which will test if any features have broken.

Back to Rewriting Cbud for the 12th+ time.

So fundamentally we changed the db to normalize it and reduce and eliminate the NEED for complex objects.

Drizzle migration:

Schema migration error: An error occurred executing the migration at step 6: no such table "drizzle"

Managing Multiple Versions of a Drizzle DB.

I can't drop tables from Turso.com so apparently I have to load prod credentials to my local site and make db edits there.

Aside: There are tags within GitHub which could make versioning much easier.

Fix make a whole different db and use raw SQL.

If I make an entirely separate DB I don't have to worry about that 401 error of not being able to drop dbs.

Start:

Tue Sep 17 2024 08:07:45 CDT

Getting prod and dev DBs figured out

"Shared schema usage error: database cannot be forked from a shared schema" on "turso".

Okay, so if it has the db logo and not the paper logo, then you can create a branch of it which is what we want.

Why use Schema db option in Turso?

Not sure why someone would chose the schema db option because of all the migration issues.

The fix that worked for me was to make to separate DBs, and if I would like to make schema changes then I

Back to the rewrite

Now that we got that figured out back to rewriting.

I would like to simplify the structure so much that I don't have to rely on LLMs (Claude) in order to get the work done. This is way better as it is easier to refine the logic and iterate upon the logic rather than a complex logic group which takes an hour to fully understand.

So in order to understand this we have to understand relates operations on a deeper level.

Start:

Wed Sep 18 2024 08:33:23 CDT

The Rewrite:

Make the app not break so fix issues which creating breaking errors*.

So we are filling in the data by hand into the db studio then we are going to show the data from the web app and then edit the data from the web app.

Add webhook to sync the local db list of users

If we just ran a webhook, and just synced it with the db that would save a whole lot of time and effort.

Start:

Thu Sep 19 2024 08:33:07 CDT

Fixing a ts issue.

Adding orgId

I think we are going to add orgId in the backend organizationID: orgId || '',

Aside: I think filler code viz. code which you want to add in the future but just having a placeholder is bad code. The code there should be there for a purpose and if its not, get rid of it.

What is InferSelectModel?

// type WorkTimeShift = InferSelectModel; Its the same thing as the $inferSelect thing just shorthand really.

Rewriting, ui/slider-component.tsx

I am looking at this and it looks like its not getting values from the RSC above it:

<SliderComponent
  initialRoutes={initialRoutes}
  selectedEmployeeID={selectedEmployeeID}
  selectedEmployeeName={selectedEmployeeName}
/>

Start:

Fri Sep 20 2024 11:09:03 CDT

We need good default values for workTimeShift.

Okay, so SQLite doesn't support set default out of the box so this makes it harder to get good default values.

Use ROWIDs.

In SQLite there is already a native mechanism for creating ids: Using the ROWID method,

This, id integer PRIMARY KEY NOT NULL,

And this should make a ROWID and you’re getting a default value id integer PRIMARY KEY,

RouteShiftInfo isn't being created when the routes are created.

Have to figure out how to make records for RouteShiftInfo as well, this may be best to do on the server.

Do we really need RouteShiftInfo

  • Yes we DO.

We just need to add it via an API file.

We don't need an API file, I guess we can you the old allocatedShifts var, currently: 34 [{"name":"Morning","startTime":"05:00","endTime":"09:00"},{"name":"Afternoon","startTime":"15:00","endTime":"19:00"}]

Rename this var to RouteShiftInfo.

The allocatedShifts var

allocatedShifts:

[
  { "name": "Morning", "startTime": "05:00", "endTime": "09:00" },
  { "name": "Afternoon", "startTime": "15:00", "endTime": "19:00" }
]

Prospective structure viz. routeShiftInfo:

Record 1:

{
  "id":5,
  "organizationID":"org_3ra423d234r",
  "routeID": "3",
  "shiftName": "Morning",
  "startTime": "05:00",
  "endTime": "09:00",
  "dateAddedToCB": "2024-09-06T22:44:52.027Z"

  },
{
  "id": 6,
  "organizationID": "org_3ra423d234r",
  "routeID": "3",
  "shiftName": "Afternoon",
  "startTime": "15:00",
  "endTime": "19:00",
  "dateAddedToCB": "2024-09-06T22:44:52.027Z"
}

New: For now on, only using ID, never Id, you can use id, if its used alone.

Aside: Using "Ctrl + Alt + -" is like using the back key. Then to go forward, use, "Ctrl + Shift + -".

This new var should formatted within a function and exported from utils/RouteShiftInfoFromAddRoute.ts. The API file will import this fn and use it.

Start:

Sep 21 2024

We need a button which is going to have some JSON info which is going to quickly add some example data.

Why is there a .0 at the end of it viz. the routeId?

Features list cbud

Generating PDF Timecards from Schedule slider.

About Feature:

PRs of this feature:

Good Tests:

Record of tests:

Editing schedules from a manager view.

URL:'/main/schedule'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment