-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #39 from Shinsina/scheduling-improvements
Scheduling and Subsessions By Track Page Additions, additional corrections
- Loading branch information
Showing
11 changed files
with
464 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export default ({ | ||
object, | ||
dateString, | ||
}: { | ||
object: Record<string, Array<string>>; | ||
dateString: string; | ||
}) => { | ||
const d = new Date(String(dateString)); | ||
const day = d.getDay(); | ||
const utcDateString = d.toUTCString(); | ||
if (day === 1 && !object[utcDateString]) { | ||
object[utcDateString] = [utcDateString]; | ||
} else if (day !== 1) { | ||
const distanceFromOne = day - 1; | ||
const dayOneOfWeek = new Date( | ||
Number(d) - distanceFromOne * 86400000 | ||
).toUTCString(); | ||
if (object[dayOneOfWeek]) { | ||
object[dayOneOfWeek].push(utcDateString); | ||
} else { | ||
object[dayOneOfWeek] = [utcDateString]; | ||
} | ||
} | ||
return object; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import determineStartOfWeekForDateString from "$lib/utils/determine-start-of-week-for-date-string"; | ||
|
||
export default ({ | ||
seasons, | ||
}: { | ||
seasons: Array<{ schedules: Array<{ start_date: string }> }>; | ||
}) => { | ||
const seasonStart = Date.UTC(2024, 2, 12, 0, 0, 0, 0); | ||
const seasonEnd = Date.UTC(2024, 4, 28, 0, 0, 0, 0); | ||
const startDates = seasons.reduce( | ||
( | ||
set: Set<string>, | ||
season: { schedules: Array<{ start_date: string }> } | ||
) => { | ||
const { schedules } = season; | ||
if (Array.isArray(schedules)) { | ||
schedules.forEach((schedule) => { | ||
const { start_date } = schedule; | ||
const [year, month, day] = start_date.split("-"); | ||
const date = Date.UTC( | ||
Number(year), | ||
Number(month) - 1, | ||
Number(day), | ||
0, | ||
0, | ||
0, | ||
0 | ||
); | ||
if (date >= seasonStart && date <= seasonEnd) { | ||
set.add(start_date); | ||
} | ||
}); | ||
} | ||
return set; | ||
}, | ||
new Set([]) as Set<string> | ||
); | ||
const weeks = Array.from(startDates) | ||
.sort() | ||
.reduce<Record<string, Array<string>>>( | ||
(object, dateString) => | ||
determineStartOfWeekForDateString({ object, dateString }), | ||
{} | ||
); | ||
return weeks; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type { Track } from "$lib/types"; | ||
|
||
export default ({ tracks }: { tracks: Array<{ track: Track }> }) => { | ||
return tracks.reduce<Map<string, { trackName: string; configName: string }>>( | ||
( | ||
map: Map<string, { trackName: string; configName: string }>, | ||
trackObject | ||
) => { | ||
const { track } = trackObject as { track: Track }; | ||
const trackName = `${track.track_name} ${track.config_name}`; | ||
map.set( | ||
trackName | ||
.toLowerCase() | ||
.replace(/[\(\)\[\]]/g, "") | ||
.replace(/[ \/]/g, "-") | ||
.replace("---", "-") | ||
.replace("-n-a", ""), | ||
{ | ||
trackName: track.track_name || "", | ||
configName: track.config_name || "", | ||
} | ||
); | ||
return map; | ||
}, | ||
new Map([]) as Map<string, { trackName: string; configName: string }> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 194 additions & 0 deletions
194
src/pages/user/[id]/scheduling/by-week/[timestamp].astro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
--- | ||
import { db, eq, User, Car, CarClass, Season } from "astro:db"; | ||
import DefaultLayout from "$lib/layouts/default.astro"; | ||
import generateSeasonWeeks from "$lib/utils/generate-season-weeks"; | ||
import determineStartOfWeekForDateString from "$lib/utils/determine-start-of-week-for-date-string"; | ||
export async function getStaticPaths() { | ||
const userIds = await db.selectDistinct({ id: User.cust_id }).from(User); | ||
const seasonsFromDb = await db.select().from(Season); | ||
const seasons = seasonsFromDb as Array<{ | ||
schedules: Array<{ start_date: string }>; | ||
}>; | ||
const weeks = generateSeasonWeeks({ seasons }); | ||
return userIds | ||
.map(({ id }) => { | ||
return Object.keys(weeks).map((weekStart) => ({ | ||
params: { id, timestamp: String(Number(new Date(weekStart))) }, | ||
})); | ||
}) | ||
.flat(); | ||
} | ||
const { id, timestamp } = Astro.params; | ||
const [user] = await db | ||
.select({ | ||
carPackages: User.car_packages, | ||
trackPackages: User.track_packages, | ||
}) | ||
.from(User) | ||
.where(eq(User.cust_id, id)); | ||
const { carPackages, trackPackages } = user; | ||
const carIds = Array.isArray(carPackages) | ||
? carPackages.map((carPackage) => carPackage.content_ids).flat() | ||
: []; | ||
const trackIds = Array.isArray(trackPackages) | ||
? trackPackages.map((trackPackage) => trackPackage.content_ids).flat() | ||
: []; | ||
const cars = await db.select().from(Car); | ||
const carsMap = new Map(); | ||
cars.forEach((car) => { | ||
const { car_id } = car; | ||
carsMap.set(car_id, car); | ||
}); | ||
// @todo Improve this query to not have to do this | ||
const carClassesResults = await db | ||
.select({ | ||
carClassId: CarClass.car_class_id, | ||
carsInClass: CarClass.cars_in_class, | ||
}) | ||
.from(CarClass); | ||
const carClassIdsForCarIds = carClassesResults | ||
.filter((result: any) => | ||
result.carsInClass.some((v: any) => carIds.includes(v.car_id)) | ||
) | ||
.map((result) => result.carClassId); | ||
// End comment of previous todo | ||
const carClasses = await db.select().from(CarClass); | ||
const carClassesMap = new Map(); | ||
carClasses.forEach((carClass) => { | ||
const { car_class_id, cars_in_class } = carClass; | ||
const carsInClass = Array.isArray(cars_in_class) | ||
? cars_in_class.map((carInClass) => carsMap.get(carInClass.car_id)) | ||
: []; | ||
carClassesMap.set(car_class_id, { ...carClass, cars_in_class: carsInClass }); | ||
}); | ||
const carClassIdSet = new Set(carClassIdsForCarIds); | ||
const trackIdSet = new Set(trackIds); | ||
const licenseGroupToNameMap: Record<string, string> = { | ||
"1": "Rookie", | ||
"2": "Class D", | ||
"3": "Class C", | ||
"4": "Class B", | ||
"5": "Class A", | ||
}; | ||
const seasons = await db.select().from(Season); | ||
const schedulesForWeek = seasons.reduce( | ||
(array: Array<Record<string, unknown>>, season) => { | ||
const { schedules, ...rest } = season; | ||
if (Array.isArray(schedules)) { | ||
const scheduleForWeek = schedules.find( | ||
(schedule) => | ||
Number( | ||
new Date( | ||
String( | ||
Object.keys( | ||
determineStartOfWeekForDateString({ | ||
object: {}, | ||
dateString: schedule.start_date, | ||
}) | ||
).pop() | ||
) | ||
) | ||
) === Number(timestamp) | ||
); | ||
if (scheduleForWeek) { | ||
const ownTrack = trackIdSet.has(scheduleForWeek.track.track_id); | ||
const ownCar = () => { | ||
if (scheduleForWeek.race_week_cars?.length) { | ||
return Boolean( | ||
scheduleForWeek.race_week_cars.filter((car: { car_id: Number }) => | ||
carIds.includes(car.car_id) | ||
).length | ||
); | ||
} | ||
const ownedCarClasses = Array.isArray(rest.car_class_ids) | ||
? rest.car_class_ids.filter((carClassId) => | ||
carClassIdSet.has(carClassId) | ||
) | ||
: []; | ||
return Boolean(ownedCarClasses.length); | ||
}; | ||
array.push({ | ||
Season_Name: rest.season_name, | ||
Track_Name: | ||
`${scheduleForWeek.track.track_name} ${scheduleForWeek.track.config_name || ""}`.trim(), | ||
Own_Car: ownCar() ? "Yes" : "No", | ||
Own_Track: ownTrack ? "Yes" : "No", | ||
Schedule_Description: rest.schedule_description, | ||
License_Level: licenseGroupToNameMap[String(rest.license_group)], | ||
}); | ||
} | ||
} | ||
return array; | ||
}, | ||
[] | ||
); | ||
const title = `Scheduling By Week - ${id} and week starting ${new Date(Number(timestamp)).toUTCString()}`; | ||
const description = title; | ||
--- | ||
|
||
<DefaultLayout {title} {description}> | ||
<div class="grid grid-cols-1 pt-6 overflow-x-scroll"> | ||
<div class="text-center col-span-1 text-2xl pb-6"> | ||
<p>Week Starts</p> | ||
<p> | ||
{ | ||
new Date(Number(timestamp)).toLocaleString("en-US", { | ||
timeZone: "America/Chicago", | ||
}) | ||
} | ||
</p> | ||
<p>This is: {new Date(Number(timestamp)).toUTCString()}</p> | ||
<p>This is considered "even" with the alternating hour being "odd"</p> | ||
</div> | ||
<table x-ref="Table" x-data="table" class="text-center col-span-1"> | ||
<tr x-ref="Headings" | ||
>{ | ||
Object.keys(schedulesForWeek[0]).map((key) => ( | ||
<th | ||
id={`Table ${key} ${schedulesForWeek.length}`} | ||
class="border-2" | ||
x-on:click="sort" | ||
> | ||
{key.replace("_", " ")} | ||
</th> | ||
)) | ||
}</tr | ||
> | ||
{ | ||
schedulesForWeek.map((result, rowNumber) => | ||
result.Own_Track === "Yes" && result.Own_Car === "Yes" ? ( | ||
<tr class="bg-green-950" x-ref={`Table ${rowNumber}`}> | ||
{Object.keys(result).map((key: string) => ( | ||
<td | ||
x-ref={`Table ${key} ${rowNumber}`} | ||
id={`${key}~${rowNumber}~${result[key]}`} | ||
class="border-2" | ||
> | ||
{result[key]} | ||
</td> | ||
))} | ||
</tr> | ||
) : ( | ||
<tr class="bg-red-950" x-ref={`Table ${rowNumber}`}> | ||
{Object.keys(result).map((key: string) => ( | ||
<td | ||
x-ref={`Table ${key} ${rowNumber}`} | ||
id={`${key}~${rowNumber}~${result[key]}`} | ||
class="border-2" | ||
> | ||
{result[key]} | ||
</td> | ||
))} | ||
</tr> | ||
) | ||
) | ||
} | ||
</table> | ||
</div> | ||
<script> | ||
import Alpine from "alpinejs"; | ||
import Table from "$lib/components/table/index.ts"; | ||
Alpine.data("table", Table); | ||
Alpine.start(); | ||
</script> | ||
</DefaultLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--- | ||
import { db, User, Season } from "astro:db"; | ||
import DefaultLayout from "$lib/layouts/default.astro"; | ||
import generateSeasonWeeks from "$lib/utils/generate-season-weeks"; | ||
export async function getStaticPaths() { | ||
const userIds = await db.selectDistinct({ id: User.cust_id }).from(User); | ||
return userIds.map(({ id }) => ({ params: { id } })); | ||
} | ||
const { id } = Astro.params; | ||
const seasonsFromDb = await db.select().from(Season); | ||
const seasons = seasonsFromDb as Array<{ schedules: Array<{ start_date: string }> }>; | ||
const weeks = generateSeasonWeeks({ seasons }); | ||
const title = `Scheduling By Week - ${id}`; | ||
const description = `Scheduling by week page for user ID: ${id}`; | ||
--- | ||
|
||
<DefaultLayout {title} {description}> | ||
<div class="text-center text-3xl"> | ||
{Object.keys(weeks).map((week) => (<div><a class="underline" href=`/Stat-N-Track/user/${id}/scheduling/by-week/${Number(new Date(week))}` rel="prefetch">{new Date(week).toLocaleString("en-US", { timeZone: "America/Chicago" })}</a></div>))} | ||
</div> | ||
</DefaultLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.