Milestones completed per version.
Okay, we have to make it so that all of the pages don't have errors then add some tests.
Then we have to add pay walls.
Then tabular content and the other issue fixing.
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.
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.
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
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:
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:
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?
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:
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:
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:
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:
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:
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:
Going to merge "issue/59" even though it's a broken Pull Request.
Start:
Working on '/main/schedule' now.
Now we can create employees we need to get them to the DOM as well as the Routes.
Start:
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:
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:
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:
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
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:
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:
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.
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:
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"
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:
[] 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:
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:
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:
[] Fix pdf
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.
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:
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.
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;
}
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:
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.
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:
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:
[
{
"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"
}
}
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.
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.
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:
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.
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"
}
}
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.
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.
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.
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.
Now, is the clerk, userID accounted for...
Don't needs stripe info because its just clerk metadata. Clerk account, we bill with Stripe.
Start:
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.
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.
We need a suite of tests to run on PR which will test if any features have broken.
So fundamentally we changed the db to normalize it and reduce and eliminate the NEED for complex objects.
Schema migration error: An error occurred executing the migration at step 6: no such table "drizzle"
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.
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:
"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.
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
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:
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.
If we just ran a webhook, and just synced it with the db that would save a whole lot of time and effort.
Start:
Fixing a ts issue.
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.
// type WorkTimeShift = InferSelectModel; Its the same thing as the $inferSelect thing just shorthand really.
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:
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.
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,
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
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.
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:
We need a button which is going to have some JSON info which is going to quickly add some example data.
Before I do that I want to get a dropdown going where you insert sample data on the Routes page because its just taking too long to insert stuff.
Aside: I think the duration of your coding session is more important than the intensity because you are thinking hard the whole time.
Start:
I wrote code which did exactly this in another project, lets dig it up and reuse it. The files mentioned: https://gist.github.com/MonteLogic/c07c5ad350f97152b5c9c2f7bb9c37f5
ToDo tomorrow:
Add the function (Chevron Dropdown) in this file ui/chevron-add-sample-route-data.tsx to the add routes page.
Start:
Okay, added the dropdown but I'm sure its crufty anyways.
The console.log for the record being added is: Route ID: 8 Type: number
So somewhere within the api file after it's being converted from 8 to 8.0.
Inserting shift info: { "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX", "routeId": 7, "shiftName": "Morning", "startTime": "05:07", "endTime": "08:01", "dateAddedToCB": "2024-09-21T22:22:35.218Z" } Inserted shift result: [ { "id": 5, "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX", "routeId": "7.0", "shiftName": "Morning", "startTime": "05:07", "endTime": "08:01", "dateAddedToCB": "2024-09-21T22:22:35.218Z" } ]
shift result is different.
The reason why is because currently the type within routeId is a string and its being casted as a string.
Ideally in the future we can have testing mechanism to test the schema file and the SQLite table matches.
Okay, now that we changed the value type from String to integer in the db we are going to focus on the next thing which is getting users from clerk into the Users table seamlessly, in all likelihood this will need a webhook or a similar mechanism.
Right now if you go on the employees page there are a bunch of users but they haven't been 'synced' manually which isn't ideal.
I think it would have been better to automatically run it and then on the employees page, there can be a way to manage the pairing. But ideally there won't even be a 'pairing' TOO MUCH WORK!
I don't even think the whole paired and unpaired should even be on the employees page; confusion creator.
The syncing logic should be nestled within the user profile('/employees/user_431faw'), IF its not matches.
I think we could have pages which fire the employee sync logic, these are going to be pages where employees/users are relevant and the check will occur there, ideally at the RSC level.
... I feel like 'Add User' should never show on its own for no employees as the person writing
Aside: Should add a date hired for the users table.
toDo: A lot of app/employees/page.tsx can be moved to the user's profile area.
There does need to be an interface for showing the pair and unpaired profiles for incoming users/employees coming into an org.
Okay, so there's an issue, the id of the db is a number but the clerk id is a string.
Its fine for now because the 0 just means that a record hasn't been created for that user, once there is a record created then an id will be generated.
Ideally we shouldn't even see the null value 0 on the employees page because a record would have already been created for each user.
We don't make id a string because we have clerkID which is already a string.
The logic for this sync only occurs on the employees page, writing the fn into a utils file and using this fn in multiple RSCs makes sense.
Fixed the slider.
ui/dropdown-users-swiper.tsx ui/dropdown-users-timecard.tsx ui/dropdown-users.tsx
d4d: Mon Sep 23 2024 18:28:59 CDT
toDo tomorrow:
Start:
The file: ui/modal-schedule.tsx
Changing the file:
Aside: I would spend some time trying to come up with a way for easier modal functionality because currently it isn't simple.
Aside: "There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult." ― C. A. R. Hoare
We fixed the modal scheduler but doesn't update w/o reload.
So it looks we are going to have to wire up a context for this.
The value which was here as an empty array was hard coded and the times of the shifts were relied upon to execute logic. https://github.com/MonteLogic/contractor-bud/blob/edb893c08dea45097a3a42dae7ab043078ef78b2/ui/slider-component.tsx#L280
This is why LLMs suck: https://github.com/MonteLogic/contractor-bud/blob/7e1cefa734d4262a936a31460ef889e6f9552036/ui/slider-component.tsx#L147
So we need to by hand address the RouteShiftInfo being brought in.
Currently I'm trying to pipe in the values via a server component.
Okay, currently all the routes are combining which we don't want we need to decipher by the route.
The context provider kind of broke it.
So we have to make the context really good and fast and hopefully we won't have these issues.
Or we can go back to using an API call.
... The route shift info time of the routes can be RSC style but the WorkTime values need to be much more snappy.
I think we need a fetch single work time and fetch org wide workTime.
So I'm guessing once we do the operation on the ModalSchedule after the POST we can update the current data to reflect the db via a useContext.
Add a boolean column, called occupied, this will be true or false.
We may have to do this for type simplicity.
Tomorrow:
dfd: Tue Sep 24 2024 22:16:56 CDT
Start:
WorkTime shifts is posting but I think the id is kinda whack which is being posted but it should be fine for now.
Currently its not reading the shift switches in the modal.
So I think this would have something to do with the context but not entirely sure.
[x] Separated files into multiple files for simplicities sake.
We need to get multiple records showing by importing all of the WorkTimeShift records for the routeID.
We need to change it from 1 to 0 for the occupied field.
I think we're going to have to make one file for the edit also, we are going to have judge if a value which is already being created is being edited because currently we don't have this.
Also, the slider view behind the modal updates just fine but I think we have to have reload the page to see the changes.
Why are the switches whack viz. they aren't showing right away but switching.
Start:
[] So we need to fix the switches so we don't need a reload.
[] We need to switch the toggle from occupied (1) to (0) on already existing records within WorkTimeShift.
I would like to run a Pull Request so we can make all of these things into issues for more streamlined fixing.
Really to fix this issue we had to make the PDF system not stupid complicated. So we did this by normalizing the database (3NF).
Now we made it easier, so I think we are going to fix all of the ts issues, issue a PR and then fix the aforementioned issues as GH issues.
Okay, so lets fix all of these ts issues and have a clean PR, also look into adding tests for PR
I think we should make id a string and just handle the id creation in the server file as this will make type safety easier.
timecards/enidan/pdfGenerator.ts
This file is so inaccurate I don't see the point in type checking it cause it needs a re write.
id: text('id').primaryKey(),
Start:
Get to working on the issue of the PDF, we gots to make the PDF real dope like.
Aside: The 'starting on:' thing is kinda wrong, it should be the current day, because the timecard generation will start on the first day of the dropdown selected.
The date is on the PDF but not the workTimeShift info.
The employee selector works as well.
The following shows on multiple users thus no filtering:
Filtered workTime: [ { "id": 944, "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX", "occupied": true, "userId": "1", "shiftWorked": "1", "dayScheduled": "2024-09-26T06:00:00.000Z", "dateAddedToCB": "2024-09-26T16:18:31.103Z", "routeId": 1, "summary": "" }, { "id": 3445, "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX", "occupied": true, "userId": "1", "shiftWorked": "2", "dayScheduled": "2024-09-26T06:00:00.000Z", "dateAddedToCB": "2024-09-26T16:18:31.435Z", "routeId": 1, "summary": "" } ] pdfGenerator.ts:173:12
workTimeForEmployees should already have the values pruned due to the fact that the dropdown mechanism can separate the WorkTimeShift table data into user based data.
So we need to go up the chain.
Side Note: I would like to be on the RSC server level for the timecard generation on the User profile.
For the file: ui/dropdown-users-timecard.tsx
const [workTimeTop, setWorkTimeTop] =
useState<WorkTimeShiftType[]>(initialWorkTime);
We are going to use setWorkTimeTop to alter the WorkTimeType data based on the selected employeeID (selectedEmployeeID)
Okay so now we got the workTimeForEmployee already filtered so now we have to draw it onto the PDF.
Aside: move network-fns into the utils folder
Start:
Lets make the PDF generation dope and then we'll go onto fixing the slider so the state transfer is way SMOOTHER. This can be done via the dropdown manipulation and issuing a GET request after a POST request has been completed, this GET request would send information down the tree.
Start:
Fixing the timecard isn't hard to do, this state transfer issue is hard to do.
Start:
Okay, so the card (in the slider) itself is being saved fine, its just the dang-on switches which are being messed up.
Whats happening is if a switch is saved and re-opened again without reloading the page then the switch just saved into the db won't show.
Maybe a GET isn't being called.
When a POST is made how come its not a unidirectional flow where we are waiting on the response from the POST because this response should have data in it.
Okay, so there is a GET request after the POST request made.
But I'm guessing its not auto updating the state.
const [localWorkTime, setLocalWorkTime] = useState<WorkTimeShiftType[]>([]);
... How about I change the macro object...
....
The update takes a long time, I think a loading wheel can be a good idea.
Also, we need to show the button state correctly.
Now, we are having issues with the cards turning blue or not if one of the nodes of WorkTimeShift is updated.
Start:
I'm going to finish up the order date toDo after I close the issue. So we are going to fix the order date today and then write a test for the whole slider, and understand the testing paradigms with SQLite/LibSQL.
Create new issue for the order date.
Start:
After a long Rosh Hosannah back to work.
toDo:
We're focusing on this:
<p>{isWorked ? "Worked" : isScheduled ? "Scheduled" : "No work"}</p>
The matter: Is not discerning isWorked from isScheduled, when we need to find out the shift as well as them time to see if it has been worked, working, or scheduled to work but hasn't worked based on the workTimeShift table.
import { WorkTimeShiftType } from "#/types/WorkTimeShiftTypes";
import { isSameDay } from "./dateUtils";
// Ideally here we would have the
export const checkShiftStatus = (
workTimeArray: WorkTimeShiftType[],
routeId: string,
date: Date,
employeeId: string
): { isScheduled: boolean; isWorked: boolean } => {
const relevantShift = workTimeArray.find((shift) => {
const routeMatch = shift.routeId === routeId;
const dateMatch = isSameDay(new Date(shift.dayScheduled), date);
const employeeMatch = shift.userId === employeeId;
return routeMatch && dateMatch && employeeMatch;
});
if (relevantShift?.occupied) {
// So we need to make discernment from the relevant shift below and
// return, willWork, isWorking, and Worked.
console.log(17, relevantShift);
}
return {
isScheduled: relevantShift?.occupied || false,
isWorked: relevantShift?.occupied || false, // You may want to add a separate 'worked' field if needed
};
};
17, { "id": "b6f8e6b2-4397-441e-ae77-9e1cb1c8806f", "organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX", "occupied": true, "userId": "1", "shiftWorked": "286d008f-0d87-4f22-ae5b-11b038610bbf", "dayScheduled": "2024-10-02T06:00:00.000Z", "dateAddedToCB": "2024-10-02T22:23:05.706Z", "routeId": "0c23aaea-195e-4683-9874-63128e60a483", "summary": "" }
I don't think we are going to get too deep into this because, we are going to make the employee work checking mechanism and that is going to involve the 'working' state. So we are just going to have isWorked and willWork.
Final product:
import { WorkTimeShiftType } from "#/types/WorkTimeShiftTypes";
import { isSameDay } from "./dateUtils";
export const checkShiftStatus = (
workTimeArray: WorkTimeShiftType[],
routeId: string,
date: Date,
employeeId: string
): { isScheduled: boolean; isWorked: boolean } => {
const today = new Date();
let isScheduled = false;
let isWorked = false;
const relevantShift = workTimeArray.find((shift) => {
const routeMatch = shift.routeId === routeId;
const dateMatch = isSameDay(new Date(shift.dayScheduled), date);
const employeeMatch = shift.userId === employeeId;
return routeMatch && dateMatch && employeeMatch;
});
if (relevantShift?.occupied) {
const shiftDate = new Date(relevantShift.dayScheduled);
if (shiftDate > today) {
// Scheduled for after today
isScheduled = true;
} else if (isSameDay(shiftDate, today)) {
// Scheduled for today
isScheduled = true;
} else {
// Scheduled for before today
isWorked = true;
}
}
return { isScheduled, isWorked };
};
....
I think it would be a good idea to test the functionality outside of the auth environment and just a local non sandbox area for the component.
So, I think we'll just have an .sqlite file as such, locally for this.
Reading this
But its verbose af, ideally the article would be on how to integrate it locally and on Vercel and be less than a 5 minute read.
Start:
Unfortunately, I don't have time to issue tests, so I'm just going to scaffold it and put it on the backburner.
Aside: I still think it would be a good idea to have tabular content on the main page, too much thinking to know the real times.
I would like for the mechanism which governs whether or not a record is shown as worked within the slider to be shared with the timecard, ideally there would only be one component for this rather than, ui/dropdown-users-timecard.tsx and ui/dropdown-users-swiper.tsx
Idk if we have time for this when we can just discriminate it like we do when distinguishing colors.
Okay, so lets make a thing which says, week 1 on the top right hand corner.
Taking code from another repo, pageNumbers
Okay, so the generator is off like way off due to the fact that we didn't account for time ranges just amount of records which is wrong.
So, we have to measure it throughout the weeks.
Okay, so we are going to use the other implementation of this, within another project, healthcare-profiler.
We start every page of with what we know, then paint from there.
The current date range: First page: 10/01/24 - 10/06/24
Second page: 10/14/24 - 10/15/24
It needs to be:
10/01/24 - 10/07/24
10/08/24 - 10/14/24
await drawDateRangeHeading(page, startDate, endDate);
const drawDateRangeHeading = async (
page: PDFPage,
startDate: Date,
endDate: Date
) => {
const startDateStr = formatDate(startDate).dateStr;
const endDateStr = formatDate(endDate).dateStr;
await drawText(page, startDateStr, 160, 709.9);
await drawText(page, "-", 222, 709.9, 14);
await drawText(page, endDateStr, 240, 709.9);
};
... The client side selector is saying 1st to 15th, it should be 1st to 14th.
...
We have too many dates written, ideally it would be just one date piped in from the top.
Now, the date ranges aren't forcing boundaries.
... So we filtered out the workTimeForEmployee, to make it fit the date ranges.
I Issue: [X] We have to fix the colon double thing in between the times,
[] Adjust the days so they all fit and not just Monday.
[] Move the time range, from the name area to the time area.
II Issue: [] Add other info from the route shift info data.
III Issue: [] Build client side functionality to build the Start and end Odometer.
Issue 99: Format the PDF, no double colon, move the name/time of the shift.
It had to do with splice stuff.
Finishing up the PDF formatting.
So we are going to split the start times up and write them.
We are going to adjust the days of the week, consolidate the data we have and then add Trip Number, Total Hours, Odometer (new feature).
Currently, not getting two pages.
Aside: a Testing scheme could be to randomly generate test data within certain boundaries, generate the timecards and look at every single one and have a hash at the top which would coordinate the testing JSON file it originated from.
https://github.com/MonteLogic/contractor-bud/issues/111
Aside: I think Claude.ai is too good to be useful. I think that there's an uncanny valley so to speak with LLMs and programming, if its too good then you're going to rely on it too much and create unreadable and not easy to modify code. Conversely, if a model is too bad, then its just unusable cause it's giving nonsense answers, so we have to find the happy medium which, I think is the 4o model or the 3.5 model from ChatGPT.
What do we need to do.... Consolidate the data we have and then add Trip Number, Total Hours, Odometer (new feature).
[x] Fix full timecards.
[] Three pages aren't being created for the latter part of the month 15-31.
.... Working on this issue: https://github.com/MonteLogic/contractor-bud/issues/112
The range is messed up, it should start on 15 not 14.
The timecard is showing 14 instead of 15 on the client component as well as on the PDF.
Switched the writing but now 15 isn't showing...
This array, workTimeTop is way too big:
const modifiedPdfBytes = await generateCBudPDF(
workTimeTop,
selectedEmployeeID,
selectedEmployeeName,
startDateObj,
endDateObj,
initialRoutes,
routeShiftInfo,
);
console.log(33, workTimeTop);
The array is truncate somewhere and it's not including, the 15 date for the latter part of it.
Where is the array truncated at?
View here: https://montelogic.com/wp-content/uploads/2024/10/Scanned_20241016-1505.pdf
I think it has something to do with the days of the weeks being written, as to why they are is still to be determined.
Timecard not showing for the full range, especially on the latter part of the month.
I want to round the corner with the timecard.
So...
Finish Time
We need to add total hours, then at the bottom, we can add contract subtotal
Add Trip number,
Replace HCR/Route number nice name with the first 6 characters of the route id which should be in the Routes table.
The end date is kind of tentative, needs to be a hard stop.
What the issue GH CLI looks like:
gh issue create --title "Issue Name 15" --body "This is the description of the issue - 43."
We are writing: gh issue create --title "Format/Finish three columns and bottom" --body " We need to add total hours, then at the bottom, we can add contract subtotal
Add Trip number,
Replace HCR/Route number nice name with the first 6 characters of the route id which should be in the Routes table. "
Okay, so we are going to use the first three
It'll be better to give the route name more space, the time space currently doesn't need to be that big.
So lets make start time and end time skinnier and expand, 'HCR/Route Number'. The trip number can have an ID next to it, but may not need this.
For the HCR it can be like '(626M5) Blueberry Town'
Also, for the total hours slot, why would it need to be as big as 'Start Time'.
We are going to shrink 'Trip Number': -10% We are going to shrink 'Start Time': -20% We are going to shrink 'End Time': -20% We are going to shrink 'Total Hours': -50% We are going to enlarge 'HCR/Route Number': +40% We are going to shrink 'Total Hours': -50% We are going to shrink 'Start Odometer': -30% We are going to shrink 'End Odometer': -30%
So we added the PDF so we now we have to link it all up.
Moving the coordinates to fit the new PDF.
Okay, so now we have to add trip number and total hours.
If we are going to add up the bottom part we should another PR for this, to large of work for one PR.
We are going to create a new PR for the bottom part.
Then we are going to fix the whole app and add payment to it.
I want to do this with the CLI instead of github.com
This is what the 'status board' looks like:
"add milestones to github projects"
Okay, so we are going to have an auto-generated .md file which will discuss the changes of the project via the milestones.
This will be a changelog of sort but with more emphasis on linking to the issues (permalinks).
If I did it we would focus on milestones but the difficulty with the GitHub UI thing is that it is very likely to change which is bad.
But the GH CLI is great even though it may change as well.
This is a good video. But she is saying to do a bunch of work with the commit message and I don't think thats the optimal way I think it would be easier to put that effort into the gh issues part.
Aside: I know barely anything about DevOps.
I think release notes aren't good for what I'm trying to do because you don't get the one view look to know the information.
Auto generating release notes, here.
Ideally the generated release notes wouldn't rely on LLM as this would increase its variability when we want consistency.
[] So we are going to add up the numbers on the bottom. #120
Okay, so we are going to add up each hours of the page and then write than on the bottom and at the end it will be all of the hours combined.
Required: Know which page we are one and if its the last one.
The employee profile page, 'employees/4' is not showing the switches for some reason.
We need to fix the rest of the app and then get pay walls up.
So let's compile the list of broken pages.
The employee page is good so
With what commit?
So, when I click me profile it seems to work but if I click employees then profile the switches aren't appearing.
Okay, so the list is showing id and note clerkId because if you visit employees/"clerkId" it works.
// Option 1: Temporarily disable post-checkout hooks
git config core.hooksPath /dev/null
I think we are going to make export to a spreadsheet paid and we are going to incorporate a hard stop on the amount of employees which a user can have before paying.
We also have to grey out switches which are taken and show alerts for them.
Title: Show other shifts other employees have done as occupied (gray-ed out)
What mechanism can we use for this?
Get the greyed out issue fixed (#124).
We need a 'Feature Book' with the features and how they were written. But it shouldn't be overwritten it should just be like natural notes. This will change in time.
So, I'm going to make an ADR and then in there we can have a file for each feature.
Now, we should have some sort of bash-like node scripts which will fire and add auto-generated notes and the folder which a new feature would be associated with.
https://montelogic.com/wp-content/uploads/2024/11/Screenshot-from-2024-11-01-12-15-21.png
We are looking at isShiftAssigned.
const isShiftAssigned = (shiftId: string): boolean => {
const shift = localWorkTime.find(
(wt) => wt.shiftWorked === shiftId.toString()
);
return shift ? shift.occupied : false;
};
Status: {
isShiftAssigned(shift.id) ? "Assigned" : "Unassigned";
}
We need to have it in a different file and in it, then it'll judge if it's assigned and it has been assigned it'll return the id string of the employee and the name of the employee as well as true, so a three value array.
So, I guess we need to base it off of the information on the dayScheduled, so a record within WorkTimeShift.
So, every single shift has its own entry, so we need to get every single available record for that day and then return the info for this record.
[
{
"id": "286d008f-0d87-4f22-ae5b-11b038610bbf",
"organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX",
"routeId": "0c23aaea-195e-4683-9874-63128e60a483",
"shiftName": "Morning",
"startTime": "06:00",
"endTime": "14:00",
"dateAddedToCB": "2024-09-27T19:26:50.274Z"
},
{
"id": "b1a72ff1-fd1e-494c-bed8-432350d3ef2b",
"organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX",
"routeId": "0c23aaea-195e-4683-9874-63128e60a483",
"shiftName": "Afternoon",
"startTime": "14:00",
"endTime": "22:00",
"dateAddedToCB": "2024-09-27T19:26:50.414Z"
},
{
"id": "0863d068-eb16-43e9-8011-0973f2aed85c",
"organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX",
"routeId": "0c23aaea-195e-4683-9874-63128e60a483",
"shiftName": "Evening",
"startTime": "22:00",
"endTime": "06:00",
"dateAddedToCB": "2024-09-27T19:26:50.650Z"
}
]
Aside: I feel like this codebase generates a lot of random values to initiate vars, like the id value shouldn't even exist. I feel like they should happen on the server level or right before it gets sent to the server because it makes it harder to debug.
It's a good codebase (I guess) but the object handling is complicated and I think there are some best practice we are for sure missing.
So, the way the switches work is that if there is no occupied shift, you will still see one element within an array but this is a bupkis value it's just auto-generated to make it 'easier' to put in but really it adds complication to the mechanism.
When it's empty:
[
{
"id": "063a4a00-73f7-48a1-ad90-8604d5fb2664",
"dayScheduled": "2024-11-21T06:00:00.000Z",
"dateAddedToCB": "2024-11-02T21:28:48.755Z",
"routeId": "0c23aaea-195e-4683-9874-63128e60a483",
"summary": "",
"organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX",
"shiftWorked": "",
"userId": "1",
"occupied": false
}
]
But when its full it will look something like:
[
{
"id": "df83c542-00b3-4880-8c2b-178b8be7bc9c",
"organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX",
"occupied": true,
"userId": "1",
"shiftWorked": "286d008f-0d87-4f22-ae5b-11b038610bbf",
"dayScheduled": "2024-11-20T06:00:00.000Z",
"dateAddedToCB": "2024-11-02T21:22:17.177Z",
"routeId": "0c23aaea-195e-4683-9874-63128e60a483",
"summary": ""
},
{
"id": "2350b075-584a-472f-93a1-6fee7a2bab48",
"organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX",
"occupied": true,
"userId": "1",
"shiftWorked": "b1a72ff1-fd1e-494c-bed8-432350d3ef2b",
"dayScheduled": "2024-11-20T06:00:00.000Z",
"dateAddedToCB": "2024-11-02T21:22:17.262Z",
"routeId": "0c23aaea-195e-4683-9874-63128e60a483",
"summary": ""
},
{
"id": "067a6dce-5e91-4dc6-81cc-311b56f06b3c",
"organizationID": "org_2fKIXFsK3Xmp0UGghHxafJHXyYX",
"occupied": true,
"userId": "1",
"shiftWorked": "0863d068-eb16-43e9-8011-0973f2aed85c",
"dayScheduled": "2024-11-20T06:00:00.000Z",
"dateAddedToCB": "2024-11-02T21:22:17.337Z",
"routeId": "0c23aaea-195e-4683-9874-63128e60a483",
"summary": ""
}
]
But now we are having issues with the fact that when a new value is writing it looks like it's overwriting all of the values.
For here,
// I feel like for here, this mapping thing, is too inaccurate, and its involving the wiping problem
// we're having viz. when another user schedules a shift for a shift day that whole day is somehow taken
// off.
const updatedWorkTime = localWorkTime.map((wt) => ({
...wt,
dayScheduled: selectedDate.toISOString(),
organizationID: orgID,
}));
There should just be an array of values we would like to change and then it's changed.
Within the server change operations there is a list which is an array of all the WorkTimeShift.
Last commit was: 12f49360a566adee9542590d75a80605cd50950d Modal switches looking better but haven't been checked copiously
I think the reason why I haven't been detailing the implementation is that I didn't know how it was implemented.
But lets write the implementation file anyways.
It should be like to get to 1.0, or 0.8 etc. All of these things should be done.
I feel like the projects panel takes too long to setup.
I feel like it would be better if there was a submodule folder where
https://cli.github.com/manual/gh_extension_browse
Definitely a good tool for downloading CLIs.
The Release Plan:
https://github.com/MonteLogic/contractor-bud/issues/119
Ideally, we would just append to this or edit this but I want to view the edit history in case there is a mistake like deletion.
So apparently, you can look up the edits made on an issue, hopefully GitHub doesn't take away this feature.
So thru the command line (GH CLI) I would like to edit 119.
I thought I fixed this but I guess not.
For commit: 65365a226dfb7787d1e770ba7e4ea0b1269eacf2
Switches show but nothing is highlighted, so we need to provide a solid source of truth.
Aside: The switches still don't have the functionality where you can see which user was assigned to a certain shift.
There are too many instances of EmployeeTabContent one for paired and another for unpaired ideally, there would just be one.
It would be great if we had tests for this so these issues don't come up, it doesn't even have to be a a VRegression tests as these take a while to setup.
So this shows with workable stuff in the console.log but for some reason it's not connecting, console.log(38, workTimeTop);
For the /schedule page I am getting the .id value for the selected thing but on profiles we are getting clerkIds....
Aside: Looking into static analysis tools for Next.js so we don't get these issues of Spaghetti code. Using SonarCube.
app/employees/[id]/page.tsx, is stuffing clerkId in there rather than the db id which workTimeTop param object uses.
This unpaired employee stuff is increasing complication like a mofo!!
Why can we not edit from the profile view yet?
No vRegression as these tests are hard to create and not the easiest to run.
Goal: Get tests written and ran for the main/slider and 'profile/slider'*
Goal: Get tests written and ran for the main/slider and 'profile/slider'*
What have I done so far for this goal?
I don't want sign in stuff via Clerk because that's like a lot of work with setting it up, ideally we can just take out the component test from there. Hopefully, this method will be less complicated then setting up testing infrastructure
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
status: 401 } ⨯ LibsqlError: SERVER_ERROR: Server returned HTTP status 401 at async Page (./app/main/schedule/page.tsx:35:29) digest: "93617260"
I think my tokens expired so have to replace them.
I changed it to prod and now I'm having table errors. Have to switch up the schema etc.
LibsqlError: SQLITE_UNKNOWN: SQLite error: no such table: WorkTimeShift at mapHranaError (file:///var/task/node_modules/.pnpm/@[email protected]/node_modules/@libsql/client/lib-esm/hrana.js:262:16) at file:///var/task/node_modules/.pnpm/@[email protected]/node_modules/@libsql/client/lib-esm/http.js:76:23 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async ew.all (/var/task/.next/server/chunks/4902.js:13:20093) at async p (/var/task/.next/server/app/main/schedule/page.js:1:10525) { code: 'SQLITE_UNKNOWN', rawCode: undefined, [cause]: [ResponseError: SQLite error: no such table: WorkTimeShift] { code: 'SQLITE_UNKNOWN', proto: { message: 'SQLite error: no such table: WorkTimeShift', code: 'SQLITE_UNKNOWN' } } }
The schema switch issues.
My local machine works fine but the prod db doesn't work.
Okay, so the team schedule looks fine but the employee list is broken.
We need to have a test for all use cases such as when there aren't any users in the employees list.
Current Issue:
Current error:
LibsqlError: SQLITE_CONSTRAINT: SQLite error: UNIQUE constraint failed: Users.id
at mapHranaError (file:///var/task/node_modules/.pnpm/@[email protected]/node_modules/@libsql/client/lib-esm/hrana.js:262:16)
at file:///var/task/node_modules/.pnpm/@[email protected]/node_modules/@libsql/client/lib-esm/http.js:76:23
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async h (/var/task/.next/server/app/employees/page.js:1:5014)
at async x (/var/task/.next/server/app/employees/page.js:1:5247) {
code: 'SQLITE_CONSTRAINT',
rawCode: undefined,
[cause]: [ResponseError: SQLite error: UNIQUE constraint failed: Users.id] {
code: 'SQLITE_CONSTRAINT',
proto: {
message: 'SQLite error: UNIQUE constraint failed: Users.id',
code: 'SQLITE_CONSTRAINT'
}
}
}
So apparently when its being imported from Clerk it's not adding anything to the ID value and thus nothing can be iterated.
Working on this issue: https://github.com/MonteLogic/contractor-bud/issues/138
Okay, which portion of the code base is responsible for Clerk import of Employees.
It should say or add this "import clerk users"
I feel like it is on /employees, on the server side because I reloaded this page and new employees were coming into the db.
Here:
async function syncOrganizationUsers(orgId: string);
None of the linters or Static Analysis tools or LLMs I have installed/used were able to spot this simple bug:
/**
* User data prepared for database insertion
* @const {User}
*/
const userData: User = {
id: "",
clerkID: clerkUser.id,
email: email,
userNiceName: userNiceName,
phone: clerkUser.phoneNumbers[0]?.phoneNumber ?? "",
img: clerkUser.imageUrl ?? "",
dateAddedToCB: currentDate,
dateHired: currentDate,
organizationID: orgId,
};
Bug Fixed:
/**
* User data prepared for database insertion
* @const {User}
*/
const userData: User = {
id: uuid(),
clerkID: clerkUser.id,
email: email,
userNiceName: userNiceName,
phone: clerkUser.phoneNumbers[0]?.phoneNumber ?? "",
img: clerkUser.imageUrl ?? "",
dateAddedToCB: currentDate,
dateHired: currentDate,
organizationID: orgId,
};
When I exported the first function, I am getting a type error.
[{
"resource": "/home/mologic/Downloads/temp/contractor-bud/.next/types/app/employees/page.ts",
"owner": "typescript",
"code": "2344",
"severity": 8,
"message": "Type 'OmitWithTag<typeof import(\"/home/monte/Downloads/temp/contractor-bud/app/employees/page\"), \"dynamic\" | \"metadata\" | \"viewport\" | \"default\" | \"revalidate\" | \"config\" | \"generateStaticParams\" | ... 6 more ... | \"generateViewport\", \"\">' does not satisfy the constraint '{ [x: string]: never; }'.\n Property 'syncOrganizationUsers' is incompatible with index signature.\n Type '(orgId: string) => Promise<void>' is not assignable to type 'never'.",
"source": "ts",
"startLineNumber": 8,
"startColumn": 13,
"endLineNumber": 25,
"endColumn": 15
}]
But it's fine for now until we figure out the testing file for this, as this is the stated goal.
Okay,
Aside: The URL for 'My Profile' isn't working again.
Aside:
Decisions:
Using the id vs. Clerk ID and which one is for which and how can we simplify it?
I think we are going to have a test instantiation of CBud Clerk user scheme.
We will query this database for the users as a JSON object and then we will copy these values in the local SQLite db.
The file we are working on: https://gist.github.com/MonteLogic/6f0c6d7ca19511d98c07d6101e994e6b
Got it so you can't commit directly to master by using the UI. You just add branch rule set, click on default and click it where you have to do Pull Requests.
Unfortunately, it looks like you're going to have to use the UI.
I still haven't figures out pre-commit hooks maybe I could figure these out in the future.
This is going to take a while and I wen't necessarily advance CBud but I'll get this testing schema for the future.
Okay, so we are going to run the db create command and then the return message and all that will tell you how it was created and the schema which was injected into it.
Off-topic Aside: I agree with the sentiment that you can tell how focused you are on a certain goal by how many things you say no to. Granted, you should still say yes to a weekly social event as this boosts your morale and increase your mood making you more more productive, note weekly.
This command should just run this file: tests/db-create/index.ts
Also, I wonder if Turso has already done this work.
Okay, they have, see: https://docs.turso.tech/local-development
For our use case, we would use, https://docs.turso.tech/local-development#sqlite
Still we have to create a testing system for our stack.
I'm going to use the local dump seen here but we don't want to do this in the future due to a whole prod db being on a local db which seems like bad security.
node -e "console.log(process.cwd())" /home/mologic/Downloads/temp/contractor-bud
Okay so I have like a testing database I can use that and could just query those test database results that'll be on like my other I think it'll be on my like my local DB and then you can just like test it or they can just like import it so they will import it onto an SQLite file and run test there.
I could use the Turso CLI but I may not need it when I can just query the users db in TypeScript.
How about I focus on running a command for testing the database
I feel like this should be a bash script which would do the db dump onto the SQLite file. Then run various tests from there.
We are using bash because when can use the Turso CLI from here and not worry about scope issues like we would if were running it from a TypeScript file. But the bash file will contain commands to run .ts files.
"test-db-users": ""
Okay so we have to do stuff like 'turso auth login' to have the CLI work so we don't want that. So we are just going to query it from within the codebase rather than running CLI commands.
I've been trying to figure out these tests since at least October 06 of last month.
So, I think I need to spend a week on just testing.
But that'll be after I fix some issues with CBud.
... I suck at testing.
local.db is created by package.json script
Will run on every Pull Requests which will mock when a user signs up for their own CBud.
Could we use a test db? We can't because there's a chance that this db will already be filled or otherwise opinionated by previous commands.
Aside:
This is too broad of an Issue Title: Create functional testing dynamic with SQLite file and Drizzle for testing Fixes #142
A better issue title would be, "create script to seed db", and it could be under the milestone of: Create functional testing dynamic with SQLite file and Drizzle for testing Fixes #142
Also, I would like to write in my work notes so I may reference a git commit or PR or other content, currently can't do this from my gist.
--
I'm not entirely a fan of using SQLiteBrowser, as it feels like late 2000s type of style, I like drizzle-kit studio or the prisma studio, so need to get these technologies to run my local SQLite files. But this seems to be the only workable option now.
So, the .env for the test db should link to the file generated and if the file is not there return an error message.
We still haven't seeded it with test db stuff, only just lorem ipsum style stuff.
So, the rule could be, for every Pull Request, these should be three tests which should run pertinent to vicinity of the code base and said feature.
Job posted see, here.
Aside: I feel like if you put a skill down describe how you used that skill rather than it just be a list because lists can be copied/pasted or AI generated.
So, I think everyone is going to have a db id but not everyone is going to have a clerk id, because the people who won't have a clerk id are the optimistic profile creations.
The params.id for this, we are going to just search the SQLite db for it, and place it there. http://localhost:3000/employees/user_2eeGhzLxDLApONQemmF4SjN4BC4
Okay, so: " We are looking for a developer who doesn't need constant guidance on what to do. There are a series of tests which testing circumstances have already been provided once these have been completed then you will be asked to make sure the codebase is under full test coverage.
This would entail going through the app comprehensively, suggest certain tests to be written, you would then create an issue on the GitHub repo and then I would approve said issue to be worked on, you would also write down the amount of time it would take to complete this task.
Then the issue would be marked approved by me.
If you can do this, I will start the contract and then you will send me your GitHub username.
The list of tasks needed to be done: Are located at: https://github.com/MonteLogic/contractor-bud/labels/testing
When you have understand the issue, quote a price in hours like previously mentioned, I would approve it, if it's below the weekly hours permitted currently 10 hours a week.
Then fix the issue, run a Pull Request and I will approve it if it remedies the issue.
Any questions, comments or concerns? "
These are like mo99 work notes:
I should have that Markdown CLI thing working so I can share my work notes.
I was looking into using WordPres but I don't want to deal with MySQL when I'm getting used to SQLite.
Maybe there is just like a Visual Editor I can instantiate like certain ones you can instantiate to view an SQLite file in the browser.
I'm thinking about using BaseHub but they could lock me into their system if I have a lot of content there and they raise their prices.
Ideally it would be self hosted.
I'm liking BCMS: https://github.com/bcms/cms
I think I'm going to give Strapi a try.
I also like this one.
Okay, what do we need done.
Incorporate the SQLite file within tests which has been instantiated using, 'pnpm run local-db-create' not a remote file.
How come I don't know the database id of the current user and I have to query it?
Aside: I would like to make the whole codebase TSDoc compliant.
I'm going to use TSDoc in the way of SonarCube because it's not catching the snags like it should.
...
I think I'm going to fix some of the issue I already have, then get TSDoc to run, then after that start testing using Stagehand as it is an easier alternative to Playwright and I see AI powered tools as the future.
.... What I would like is for the AI to grab onto the certain html selection sequence and return this hard coded value, and we can use this hard coded value as a saved value or ask the AI again.
Aside: It's a good idea to add the thing where you edit Firefox to make the background black on mo99, the setup part. This is due to the fact that it is too bright when your working in ctrl+shift+m mode(mobile mode).
Okay, so I have to make my CMS Markdown CLI thing because I need to make a /docs page and a /blog page as well as other marketing pages .
In reference to this blog post.
I want to make it self-hostable but I don't want to do it on like Namecheap, ideally AWS or a service where I can hopefully pay pennies on the Dollar.
Let's try out Strapi first as a self-hosted option on AWS.
Render seems to be the most easy to use and faster to prod one.
Okay, not using Strapi, using PayloadCMS.
Got the Payload CMS on my system now need to detach the frontend and add the frontend and other parts to Payload CMS. Wait, I'm tripping, I don't have to detach because these are the docs/blog. Maybe in the future we can do the aforementioned tasks but for now, NO NEED!
It would be great if you could log into the admin via Clerk.
On vercel, I want to add another project, cbud.app/info, while cbud.app is already taken, I would like to add another project.
It would probably be better to do the "aforementioned" tasks in order to get this structure to work.
Also, I would love to switch my personal blog, to this format.
I feel like this would entail rewriting cbud which will take a while, so I think I'm going to use a subdomain and what I'll do is refactor my personal blog to learn how to refactor various Next.js app to use PayloadCMS.
So, it's going to be (info.cbud.app)[https://info.cbud.app]
But I would like to make it a git submodule so there isn't a bunch of commits hopefully we can do this without accruing to much technical debt.
Honestly at this point I feel like just setting up the paywall and just running a bunch of ads before writing docs, but in order to do this, we have to setup tracking.
And I think I'll make the monthly cost small, 15 dollars a month.
Sidenote: We also need analytics.
The paywall should be setup so if generate more than 5 timecards in a month then you have to pay 20 dollars.
I also think optimistic profile creation should be a premium feature.
If you have more than 1 employee than
The goal is to have users on the app a lot because then they're more likely to buy.
So maybe we could have a payment status bar...
I think the org switcher would be better in the setting and where the org is at in the bar what we could have is the payment status stuff and more info about the current user. The profile thing, I think that can stay but the Org Switcher can be moved to settings and the "org:member" data will be in the new truncated, payment status bar.
On this "truncated bar" we will have an easy way to update payment to make the payment movement easier.
The so called bar I'm trying to redesign is located at: ui/address-bar.tsx
"a Next.js 13 component using tailwind which will be kind of like the OrgSwitcher from Clerk but instead it will show information about the payment status of a user."
Worked on modal, now any click off modal/window closes the window.
I would like quick way from the drop down to see if a certain user is even scheduled.
Seen here.
But this is later we need to get the pay wall good.
We are tracking:
So we are going to track amount of timecards generated in a 30 day period.
Amount of employees in the system.
How long the CBud system is up.
Side Note: We could have a GM profile permission (think WoW).
The state of the address bar persists.
When I used the route push to /settings and I didn't program the modal to close, the modal stayed open on /settings.
We need to get Stripe connected to all of this.
We don't have a way to record timecards generated but we have an employees limit, viz. we know how many employees an org has.
This is answer is good, here
So we got the dummy UI setup for Stripe.
Working on this issue: https://github.com/MonteLogic/contractor-bud/issues/156
Looking at clerk.com metadata field.
The relevant response: https://claude.ai/chat/445cda0f-f4ac-4426-88a0-338ddcc6dfdb
Okay, right now, it's saying 'No active subscription' how can we get the subscription linked up?
Okay, so we want to get this thing linked up.
apiVersion: '2024-12-18.acacia',
Focusing on the Stripe part and iterating on the Stripe part.
Sidenote: took a Nootropic now I can focus on coding when I was once struggling.
The current metadata for the main email: my initial followed by my real last name.
localDbId:"user_2eeGhzLxDLApONQemmF4SjN4BC4"
Now getting the relevant info from Stripe so we can pass it into Clerk.
https://dashboard.stripe.com/test/developers
the customer id of the main email: cus_OulWbLeTkoHmCN
Sidenote: there's embedded payments for Stripe but probably won't use that soon.
UI Sidenote: That payment status thing should be changed to login when there isn't a user signed in.
I'm getting the session id thing injected to my url: localhost:3000/settings?session_id=cs_test_a12HWGVYIHl5iiP2ydL0lFAkJzWvtbWmDlULjGNonGAxTADh9X7qfXEGjz
This piece of code, here makes it so you can append the metadata but we are in a situation where a user can double buy and so on.. Also there isn't a sign that the user has bought the sku.
Realized the issue was: devDependencies: skipped because NODE_ENV is set to production
Need to figure out how to differentiate between needed prod and dev packages.
Okay, so I spent a day on git issues rather than making progress because I didn't want to commit to master due to a lock file being bad, among many other conflicts.
So I need a function which is going to check their status, this could either be via sever call or POST call.
Did show the status of the Stripe thing.
...
Okay, so I'm going to make it like, you are on x plan and you have generated x amount of timecards, so like 'timecards: unlimited'
...
That's turning out to be a lot of work when I just need to get a simple paywall working .
Here we have to change it for the server component stuff: app/layout.tsx
Then later we could have an API call which could modify the original RSC data.
So, I gotta pipe in data via the server component which is going to bring in data from Stripe metadata regarding their plan and if they don't have a plan then it's just going to show free with how many timecards they have but now. Focus on the server component.
The issues we have now are too broad, need to be split up, and made easier to achieve.
Why is it like "Plan: prod_5235345"
We need to get rid of the Plan: and have it just be the prod* or dev* string
<PaymentStatusSwitcher
paymentInfo={{
status: subscriptionData.status.isActive
? PaymentStatusEnum.ACTIVE
: PaymentStatusEnum.CANCELED,
plan: `Plan: ${subscriptionData.status.planId}`,
nextBilling: `Expires: ${subscriptionData.status.expiresAt}`,
recentTransactions: [],
}}
Straight from the server it looks like: 24 { status: { isActive: true, planId: 'prod_RRpMROFi5ZgEEF', expiresAt: '2025-01-24T17:26:53.000Z' } }
/** Current subscription status information */
export interface StripeSubscriptionStatus {
status: {
/** Whether subscription is currently active
* "active" | or another option
*/
isActive: boolean;
/** Stripe product ID for subscription plan */
planId: string;
/** ISO timestamp when subscription expires */
expiresAt: string;
/** Array for transactions **/
recentTransactions: Array<string>;
};
}
I think I might have to use a local db over Clerk metadata as I need a way to track the amount of timecards and other resources used by users.
On the home page there isn't a way to just sign in, need to add a bar or something like this to fix it. Maybe add sign in to bar,
So, add sign in in component on protected pages.
We might be find with just the basic plan. So, we'll just do the basic plan and you'll get unlimited timecards.
On the timecard page, we need to put a limiter on it, and a link to upgrade near the limiter. There are 5 timecards a month.
So above Generate Timecards it'll be like timecards generated and it'll be different if they have a plan etc.
I think I might put the generate timecard count within Clerk metadata.
In order to do that we need to get the org stuff good, so lets put org switcher in main/settings.
So, ideally we could just toggle the org switcher and the plans could differ. SO if an org has a limited/free plan and one has an unlimited the plan/ timecard generated view should change immediately based on the org switching.
The summaries page should be punted for now
Current focus is to put the numbers of timecard generated into Clerk metadata.
I think I'll store it in publicMetadata.
I learned that you can fix conflicts in git by just copying and pasting the current main file.
Also learned how it's important to ALWAYS run your start command before a dev session.
So today the focus is on Clerk metadata.
Side Note: What I've noticed is if it's a new way of doing things and we are LEARNING than it's tougher on the brain so you should slim down your stuff so your doing more of the same thing. So with this in mind it may've been better to hold stuff in local db but I should've used Clerk metadata more cause it's easier to use and not so much slow spin up times.
We are going to be using Clerk public metadata to store the data we plan on using.
git pull
git pull origin master From https://github.com/MonteLogic/my-project
So, we have to tie that good counter in with the actual timecard generator probably via props so we can fragment into different files and then from there we will be able to know their payment status and charge accordingly.
User Details should be a Log in button when not logged in.
Replace dummy data with real metadata
Make the org:member look better and with a link to the org switcher.
The modal should be closed when a new page is visited, the router is persisting the modal when routes are changed.
I'm focusing on stuff to do when I'm to tired to code.
So Chess, learn languages, read books,
But I think I'm going to look at codebases on GitHub.
"next": "14.0.3-canary.7",
So we are just looking for a bunch of codebases really.
That string really didn't work because it seems to be specifically for Next.js App Router Playground.
https://github.com/vercel/commerce
https://github.com/payloadcms/payload
https://github.com/blitz-js/blitz
https://github.com/shuding/nextra
Okay, so I would still like to blog out that stuff related to codebases but I forgot my blogging work stack.
I have a list of issues to work on.
For today:
Generate Timecard on Profile
Enforce Stripe Paywall
Side note: For GH Issues I wish there was a very quick way to show importance of getting the issue done and it would be like a slider.
Solution: Maybe I could just make a GH Issue template for this.
Side note: This GH Extension doesn't explicitly use GitHub themed extension and services a Slack workflow, seen here.
Make a bash file, seen [here] (https://gist.github.com/MonteLogic/a785a079a52e7b4947902e74a2d01df6)
Side Note: It would be dope if there was a mechanism for me to search within a git repo to see if a certain part of the app has been tinkered with.
MonteLogic/issue172
Okay, I would like to rewrite the timecard component as little as possible so I don't have to maintain two components much less two very similar components.
These two files,
ui/employees/EmployeeTabContent.tsx
&
app/employees/[id]/EmployeePage.tsx
are very similar, looking into combining them.
Deleting this: app/employees/[id]/EmployeePage.tsx
Deleted this file and no noticeable difference.
For thistext, I will probably end up putting the timecards generated into TimeCardComponent to make it more portable. But for now, I'm just going to import TimeCardComponent.
So, I just imported it and made a few minor changes to imports. So now, bringing in the metadata counter into the TimeCardComponent.
ToDo: Add labels to descriptions.
Was going to start the Paywall enforcement but that PDF needs to have User Nice name, etc.
When you update the timecard you have to refresh the page in order to see the changes, need to fix this.
We're going to have to do some sort of date filter logic because right now I'm just querying i think the whole orgs data which is bad for server usage. It may be the WHOLE database for all I currently know
Need to refactor it. Or otherwise reorganize it.
So, we need to have the slider show every day on the modal which the view button corresponds too.
We also need a good loading state for the switches.
Also, sometimes the switch is toggled but it's not lit up in yellow for scheduled.
On my local machine not seeing it, going to try now with prod.
Still can't reproduce bug, I think it had something to do with the slowness of the updates.
Assigned to should actually show which user it is assigned to rather than saying it's just assigned.
We could even have an arrow when the modal is up. Which could slide the slider as well. So if the modal is up on say Jan 22nd you could just hit the right arrow and it would go to Jan 23rd.
For team schedule it doesn't make sense to not have a wholistic view. It is all view from the view of the single employee. This is fine if you are on a profile page but when it says Team Schedule, you should be able to view the whole schedule. Also, on profile, I think there should be a switch where you can toggle on team view.
Replace acme timecard with CBud timecard.
Just going to fix assigned to, issue180 and setup paywall and send traffic.
Not only that, it's not even adding to the db and there is no logging showing that it isn't.
Okay, so I showed the other views now, what we could do is work on the holistic view but that'll be after we send traffic to it.
I think if there's a dev instance than this enforcement should be waived.
We need to fix the timecard because now it's showing all of the shifts. We need better filtering!
So we could move the real timecards generated number to replace the dummy number in the summary-bar.
We're going to need Modals to show the payment arrangement/tiers.
If it's a test instance then I don't want any walls, so we are going to check the .env variable to see if it's prod and then we'll enable the Stripe paywalls.
We could also have another .env which will be like STRIPE_PAYMENT_WALL and we could turn this on for dev instances to test the Stripe paywall.
So let's create this countdown of sorts and then it'll lock the button and when they want to press it again they are presented the modal.
So goal, make a timecard count down which will show a modal with the tiers.
Also we have to fix the payments area as it's just not working.
So the scheme is going to be after
They get a bank of 20 timecards a month and it won't show up that it's locked until they have 5 left.
Okay, so I would like to make it more like the Vercel billing section due to the fact that, there too much data and business logic to fit on one small page.
So, the tiers will be pro and max, see.
The milestone seen, here.
Again enforcing the paywall is a broad tasks. So the issue should be lock the timecard generation to 20.
Also, I wonder if we could find an easy way to switch thru different tiers. 'free', 'pro', 'max', 'enterprise'.
Lock timecards generated to 20 for free accounts, present paywall modal on the 20th one. #173
The system needs to know what tier it's in.
We do have the current plan, sku which would be like, prod_RRpMROFi5ZgEEF
But what tier is this we need to know the tier so we can enforce rules accordingly.
So it'll be like view more about plans, next to the user's plan.
I am in favor of just making it ISR and apart of the apart of the app for now instead of a lot of stuff.
So it should be available to the public, so not a protected route.
I think I'm going to add markdown files but locally and try not to over complicate the process because we are going to have a docs/blog site to handle this further.
Instead of just adding Markdown to it, I could write out the HTML by hand.
The plan/tier a user has is important to know for almost every component so we should figure out how to get it via Server component as well as the current* API query.
... Redeem Credits?
ShadCN Drawer for upsells.
This repo has usable code, here.
We gotta make the settings page like a drawer sort of dropdown because we're not going to make it like Vercel's UI because that would be exorbitant work.
So get the drawers good, on '/settings'.
Currently it's all black for some reason.
So the next thing is to, make the settings page have a better view and operations to make a user upgrade their plan.
The tabs are going to look like:
Main Settings | Upgrade | Invoices | Contact Desk
and Main Settings will just have a summary of stuff and the links will just take the user to that one area within the tab.
Similar to WooCommerce settings page, seen here.
Side Note: If your not picking up the intellisense try typing import, then get the intellisense autocomplete for the piece of code you're looking for.
It would be great if there was a dropdown thing for admin accounts where you can switch through the different tiers to see what the state looks like.
Currently users just can't upgrade easily and we NEED to change that.
This is having import problems: app/settings/plans/components/pricing-cards.ts
But this is fine: app/settings/components/plans/file1.tsx
I like the layout better but it should be the colors of the current #189
https://contractor-buddy-pofn35p52-montelogics-projects.vercel.app/docs/plans
You should be able to hover over it
On mobile, the first looks way better.
Also, the whole element element should be clickable on Desktop but for now with the mobile it's fine. We need to link the ids of the plans from Stripe in data.ts.
pro: process.env.TEST_PRO_PLAN, This is undefined
[email protected] is a fresh sign up.
I am currently try to get the settings page good.
I was trying to get the products shown good, for test and prod.
Added this to the .env: NEXT_PUBLIC_ENV='dev'
So we should be able to tell if it's dev or not and then load products accordingly.
So going to read the env from above and get the correct products from products folder.
I got the products loaded up which is good so we're ready to send traffic.
Now they are viable after the last PR.
What I would like to do is, have every new user just start with a blank route and then they can easily customize it.
But we need to get this to market so lets do that.
I think there should be a Contact support page that sends their ticket to the db and there should be notifications to Admins to address their requests.
Contact page (must be paid)
Every 20 minutes, a popup with an indication to upgrade.
We need to install analytics for CBud so we know what's going on.
https://github.com/vercel/next.js/tree/canary/examples/with-google-analytics
GTM: https://github.com/vercel/next.js/tree/canary/examples/with-google-tag-manager
It looks like I'm going to have to rewrite my app to use Next.js 15+ and I'm really NOT trying to that right now so, I'm going to do Vercel Web Analytics.
So we use blogs to drive traffic and currently I have a different domain for the traffic, this makes analytics and tracking more difficult. I like Payload with the UI and other features but I don't see an easy to integrate it into my current stack.
Apparently I can do something like: the-project/ ├── apps/ │ ├── web/ # Your Next.js 14 app │ └── cms/ # Payload CMS └── package.json
I may just drop Payload as I don't want to bring in the extra stuff when I really like my current stack.
I'll have a folder called articles which I could store on a server somewhere and it'll just be queried in.
Use GitHub to store the Markdown articles and query them.
My problem is that I don't feel like doing it anymore. But I found some motivation.
I really don't want to make the blog a different page, I'd rather keep what I have and just add a
How does the blog in payload differ and can we combine the two because I would really like to do this.
Okay, so Payload isn't all that lightweight so we're just going to have separate thing with Payload or add the articles manually.
So how about in the menu state there could be the state where it's in the docs side, and then you can go to app then there's an app state menu.
If I were to do it again I would pick the repo above and it's Next.js 15+ so the Google Analytics component is much more likely to work.
So the GH thing is working well, so what I would like to do is have a blog section.
So we are adding a Blog page to the menu.
So, in mobile mode there will be a sandwich menu but in desktop mode there will be more options in a sort of landscape look and there would be a sandwich menu on the end.
Okay, so it should be a blog feed and show all of the recent posts.
I think it would be dope if there was a third menu which showed their latest blog posts viewed.
I want a views counter for all the blog posts.
The preview data for sharing the posts on social media isn't good, still working on this.
This is getting stuck in an infinite loop: https://contractor-buddy-fku5skq3e-montelogics-projects.vercel.app/
Fresh usable from the start: #200
Replace dummy data: Timecards Generated: 0
Timecards Left: 2
Employees: X View Organization
Improve blog look
Setup funnel with Mailgun.
Paywall should be stricter.
Blog needs to have social metadata as well as images.
Text on blog should be more readable.
Make social media look better, photos of myself on there.
In the menu area there should be an Upgrade link.
So, apparently there's a standard-modal
ui/standard-modal.tsx
Working on issue 201.
What I would like to do is to get Google Analytics working good before I pay for traffic.
But let's just pay 15 dollars and then after that if there is no sale than Google Analytics.
It should be a graph (nodes) of how everything works when it was tested last. Almost like a suite for current features, a switchboard if you will.
Not seeing an off the shelf solution for this probably going to have to create a custom solution for this.
...
Local solution which will rely on GH Issues for marking and managing issues.
You could just run 'pnpm start switchboard'
This message:
"You are not a part of an organization, Create Organization"
Rather it should always show the slider.
Page app/main/schedule/page.tsx
...
Solution:
You are not a part of an organization, start CBud, or get invited to an organization.
So it should be:
Start CBud, or request invitation.
And if they start CBud then it should have all the stuff auto-filled and then they can just mindlessly click thru the prompts until they get the schedule view.
About Feature:
PRs of this feature:
Good Tests:
Record of tests:
URL:'/main/schedule'
We could have links to all of the relevant pages within say, the issue of 119 so.
Branch: summary-page with be a permalink to a page where we are describing the ongoing work with this feature.
# .github/release.yml | |
changelog: | |
exclude: | |
labels: | |
- ignore-for-release | |
authors: | |
- octocat | |
categories: | |
- title: Breaking Changes 🛠 | |
labels: | |
- Semver-Major | |
- breaking-change | |
- title: Exciting New Features 🎉 | |
labels: | |
- Semver-Minor | |
- enhancement | |
- title: Other Changes | |
labels: | |
- "*" |