From a756737601574c97c522fe11748aaffcd43b9fe0 Mon Sep 17 00:00:00 2001 From: BudzioT Date: Fri, 13 Dec 2024 18:57:15 +0100 Subject: [PATCH 1/4] Update project selection, bugs out --- src/app/harbor/shipyard/new-update-form.tsx | 133 ++++++++++++++++---- src/app/harbor/shipyard/ship-utils.ts | 5 +- src/app/harbor/shipyard/ships.tsx | 1 + 3 files changed, 116 insertions(+), 23 deletions(-) diff --git a/src/app/harbor/shipyard/new-update-form.tsx b/src/app/harbor/shipyard/new-update-form.tsx index 6e72563c..6170533c 100644 --- a/src/app/harbor/shipyard/new-update-form.tsx +++ b/src/app/harbor/shipyard/new-update-form.tsx @@ -3,9 +3,10 @@ import { createShipUpdate } from './ship-utils' import type { Ship } from '@/app/utils/data' import { Button } from '@/components/ui/button' import JSConfetti from 'js-confetti' -import { useCallback, useEffect, useRef, useState } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' import { getWakaSessions } from '@/app/utils/waka' import Icon from '@hackclub/icons' +import { MultiSelect } from '@/components/ui/multi-select' export default function NewUpdateForm({ shipChain, @@ -13,17 +14,38 @@ export default function NewUpdateForm({ closeForm, session, setShips, + ships }: { shipChain: Ship[] canvasRef: any closeForm: any session: any setShips: any + ships: Ship[] }) { const [staging, setStaging] = useState(false) const [loading, setLoading] = useState(true) const confettiRef = useRef(null) const [projectHours, setProjectHours] = useState(0) + const [projects, setProjects] = useState< + { key: string; total: number }[] | null + >(null) + const [selectedProjects, setSelectedProjects] = useState< + | [ + { + key: string + total: number + }, + ] + | null + >(null) + + const newWakatimeProjects = selectedProjects?.join('$$xXseparatorXx$$') ?? '' + const prevWakatimeProjects = shipChain[shipChain.length - 1].wakatimeProjectNames?.join('$$xXseparatorXx$$') ?? '' + let wakatimeProjectNames = prevWakatimeProjects + if (newWakatimeProjects && newWakatimeProjects !== '') { + wakatimeProjectNames = prevWakatimeProjects + '$$xXseparatorXx$$' + newWakatimeProjects + } // Initialize confetti on mount useEffect(() => { @@ -40,18 +62,47 @@ export default function NewUpdateForm({ } }, []) + // Fetch projects from the API using the Slack ID + useEffect(() => { + async function fetchProjects() { + try { + if (sessionStorage.getItem('tutorial') === 'true') { + setProjects([{ key: 'hack-club-site', total: 123 * 60 * 60 }]) + } else { + const res = await getWakaSessions() + const shippedShips = ships + .filter((s) => s.shipStatus !== 'deleted') + .flatMap((s) => s.wakatimeProjectNames) + setProjects( + res.projects.filter( + (p: { key: string; total: number }) => + p.key !== '<>' && !shippedShips.includes(p.key), + ), + ) + } + } catch (error) { + console.error('Error fetching projects:', error) + } + } + fetchProjects() + }, [ships]) + const calculateCreditedTime = useCallback( ( projects: { key: string total: number }[], + newProjects: string[] | null, ): number => { const shipChainTotalHours = shipChain.reduce( (acc, curr) => (acc += curr.credited_hours ?? 0), 0, ) console.log({ shipChain, shipChainTotalHours }) + const newProjectsHours = projects.filter((p) => + newProjects?.includes(p.key), + ).reduce((acc, curr) => (acc += curr.total ?? 0), 0) const ps = projects.filter((p) => (shipChain[0].wakatimeProjectNames || []).includes(p.key), @@ -59,37 +110,38 @@ export default function NewUpdateForm({ if (!ps || ps.length === 0) return 0 - const total = ps.reduce((acc, curr) => (acc += curr.total), 0) + const total = ps.reduce((acc, curr) => (acc += curr.total), 0) + newProjectsHours const creditedTime = total / 3600 - shipChainTotalHours return Math.round(creditedTime * 1000) / 1000 }, [shipChain], ) - useEffect(() => { - async function fetchAndSetProjectHours() { - setLoading(true) - const res = await fetchWakaSessions() - - if (res && shipChain[0].total_hours) { - let creditedTime = calculateCreditedTime(res.projects) - console.log('Flow one', { ps: res.projects, creditedTime }) - - if (creditedTime < 0) { - const anyScopeRes = await fetchWakaSessions('any') - if (anyScopeRes) { - creditedTime = calculateCreditedTime(anyScopeRes.projects) - console.error('fetchAndSetProjectHours::Flow two', { creditedTime }) - } - } + const fetchAndSetProjectHours = useCallback(async (newProjects: string[] | null) => { + setLoading(true); + const res = await fetchWakaSessions(); - setProjectHours(creditedTime) + if (res && shipChain[0].total_hours) { + let creditedTime = calculateCreditedTime(res.projects, newProjects); + console.log('Flow one', { ps: res.projects, creditedTime }); + + if (creditedTime < 0) { + const anyScopeRes = await fetchWakaSessions('any'); + if (anyScopeRes) { + creditedTime = calculateCreditedTime(anyScopeRes.projects, newProjects); + console.error('fetchAndSetProjectHours::Flow two', { creditedTime }); + } } - setLoading(false) + + setProjectHours(creditedTime); } + setLoading(false); + }, [fetchWakaSessions, calculateCreditedTime, shipChain]); - fetchAndSetProjectHours() - }, [fetchWakaSessions, calculateCreditedTime, shipChain]) +// Use fetchAndSetProjectHours in useEffect + useEffect(() => { + fetchAndSetProjectHours(null); + }, [fetchAndSetProjectHours]); const handleForm = async (formData: FormData) => { setStaging(true) @@ -122,6 +174,12 @@ export default function NewUpdateForm({ } } + const projectDropdownList = projects?.map((p: any) => ({ + label: `${p.key} (${(p.total / 60 / 60).toFixed(2)} hrs)`, + value: p.key, + icon: () => , + })) + return (

@@ -152,6 +210,37 @@ export default function NewUpdateForm({ className="w-full p-2 rounded bg-white/50" /> + {/* Project Dropdown */} +
+ + + {projects ? ( + { + setSelectedProjects(p); + await fetchAndSetProjectHours(p); + }} + defaultValue={[]} + placeholder="Select projects..." + variant="inverted" + maxCount={3} + /> + ) : ( +

Loading projects...

+ )} + + {/* Hidden input to include in formData */} + +
+

)} From 5cfa716debe42d09e6c754b6864fb2cdd156cedc Mon Sep 17 00:00:00 2001 From: BudzioT Date: Fri, 13 Dec 2024 20:55:13 +0100 Subject: [PATCH 3/4] Prettier shipyard --- src/app/harbor/shipyard/new-ship-form.tsx | 3 +- src/app/harbor/shipyard/new-update-form.tsx | 81 ++++++++++++--------- src/app/harbor/shipyard/ship-utils.ts | 7 +- src/app/harbor/shipyard/ships.tsx | 7 +- 4 files changed, 56 insertions(+), 42 deletions(-) diff --git a/src/app/harbor/shipyard/new-ship-form.tsx b/src/app/harbor/shipyard/new-ship-form.tsx index 51933761..7ba40153 100644 --- a/src/app/harbor/shipyard/new-ship-form.tsx +++ b/src/app/harbor/shipyard/new-ship-form.tsx @@ -111,7 +111,6 @@ export default function NewShipForm({ p.key !== '<>' && !shippedShips.includes(p.key), ), ) - } } catch (error) { console.error('Error fetching projects:', error) @@ -121,7 +120,7 @@ export default function NewShipForm({ }, [ships]) useEffect(() => { - setUsedRepos(ships.map(ship => ship.repoUrl)) + setUsedRepos(ships.map((ship) => ship.repoUrl)) }, [ships]) const handleForm = async (formData: FormData) => { diff --git a/src/app/harbor/shipyard/new-update-form.tsx b/src/app/harbor/shipyard/new-update-form.tsx index 17e6dc85..f79ed2a9 100644 --- a/src/app/harbor/shipyard/new-update-form.tsx +++ b/src/app/harbor/shipyard/new-update-form.tsx @@ -14,7 +14,7 @@ export default function NewUpdateForm({ closeForm, session, setShips, - ships + ships, }: { shipChain: Ship[] canvasRef: any @@ -32,19 +32,23 @@ export default function NewUpdateForm({ >(null) const [selectedProjects, setSelectedProjects] = useState< | [ - { - key: string - total: number - }, - ] + { + key: string + total: number + }, + ] | null >(null) const newWakatimeProjects = selectedProjects?.join('$$xXseparatorXx$$') ?? '' - const prevWakatimeProjects = shipChain[shipChain.length - 1].wakatimeProjectNames?.join('$$xXseparatorXx$$') ?? '' + const prevWakatimeProjects = + shipChain[shipChain.length - 1].wakatimeProjectNames?.join( + '$$xXseparatorXx$$', + ) ?? '' let wakatimeProjectNames = prevWakatimeProjects if (newWakatimeProjects && newWakatimeProjects !== '') { - wakatimeProjectNames = prevWakatimeProjects + '$$xXseparatorXx$$' + newWakatimeProjects + wakatimeProjectNames = + prevWakatimeProjects + '$$xXseparatorXx$$' + newWakatimeProjects } // Initialize confetti on mount @@ -100,48 +104,57 @@ export default function NewUpdateForm({ 0, ) console.log({ shipChain, shipChainTotalHours }) - const newProjectsHours = projects.filter((p) => - newProjects?.includes(p.key), - ).reduce((acc, curr) => (acc += curr.total ?? 0), 0) + const newProjectsHours = projects + .filter((p) => newProjects?.includes(p.key)) + .reduce((acc, curr) => (acc += curr.total ?? 0), 0) const ps = projects.filter((p) => - (shipChain[shipChain.length - 1].wakatimeProjectNames || []).includes(p.key), + (shipChain[shipChain.length - 1].wakatimeProjectNames || []).includes( + p.key, + ), ) if (!ps || ps.length === 0) return 0 - const total = ps.reduce((acc, curr) => (acc += curr.total), 0) + newProjectsHours + const total = + ps.reduce((acc, curr) => (acc += curr.total), 0) + newProjectsHours const creditedTime = total / 3600 - shipChainTotalHours return Math.round(creditedTime * 1000) / 1000 }, [shipChain], ) - const fetchAndSetProjectHours = useCallback(async (newProjects: string[] | null) => { - setLoading(true); - const res = await fetchWakaSessions(); + const fetchAndSetProjectHours = useCallback( + async (newProjects: string[] | null) => { + setLoading(true) + const res = await fetchWakaSessions() - if (res && shipChain[0].total_hours) { - let creditedTime = calculateCreditedTime(res.projects, newProjects); - console.log('Flow one', { ps: res.projects, creditedTime }); + if (res && shipChain[0].total_hours) { + let creditedTime = calculateCreditedTime(res.projects, newProjects) + console.log('Flow one', { ps: res.projects, creditedTime }) - if (creditedTime < 0) { - const anyScopeRes = await fetchWakaSessions('any'); - if (anyScopeRes) { - creditedTime = calculateCreditedTime(anyScopeRes.projects, newProjects); - console.error('fetchAndSetProjectHours::Flow two', { creditedTime }); + if (creditedTime < 0) { + const anyScopeRes = await fetchWakaSessions('any') + if (anyScopeRes) { + creditedTime = calculateCreditedTime( + anyScopeRes.projects, + newProjects, + ) + console.error('fetchAndSetProjectHours::Flow two', { creditedTime }) + } } - } - setProjectHours(creditedTime); - } - setLoading(false); - }, [fetchWakaSessions, calculateCreditedTime, shipChain]); + setProjectHours(creditedTime) + } + setLoading(false) + }, + [fetchWakaSessions, calculateCreditedTime, shipChain], + ) -// Use fetchAndSetProjectHours in useEffect + // Use fetchAndSetProjectHours in useEffect useEffect(() => { - fetchAndSetProjectHours(null); - }, [fetchAndSetProjectHours]); + fetchAndSetProjectHours(null) + }, [fetchAndSetProjectHours]) const handleForm = async (formData: FormData) => { setStaging(true) @@ -220,8 +233,8 @@ export default function NewUpdateForm({ { - setSelectedProjects(p); - await fetchAndSetProjectHours(p); + setSelectedProjects(p) + await fetchAndSetProjectHours(p) }} defaultValue={[]} placeholder="Select projects..." diff --git a/src/app/harbor/shipyard/ship-utils.ts b/src/app/harbor/shipyard/ship-utils.ts index 358e47e4..348ed71c 100644 --- a/src/app/harbor/shipyard/ship-utils.ts +++ b/src/app/harbor/shipyard/ship-utils.ts @@ -67,7 +67,9 @@ export async function createShip(formData: FormData, isTutorial: boolean) { update_description: isShipUpdate ? formData.get('updateDescription') : null, - wakatime_project_name: formData.get('wakatime_project_name')?.toString(), + wakatime_project_name: formData + .get('wakatime_project_name') + ?.toString(), project_source: isTutorial ? 'tutorial' : 'high_seas', for_ysws, }, @@ -122,7 +124,8 @@ export async function createShipUpdate( * Secondly, the reshipped_to field on the reshipped ship should be updated to be the new update ship's record ID. */ - const wakatimeProjectNames = formData.get('wakatime_project_name')?.toString() || ''; + const wakatimeProjectNames = + formData.get('wakatime_project_name')?.toString() || '' // Step 1: const res: { id: string; fields: any } = await new Promise( diff --git a/src/app/harbor/shipyard/ships.tsx b/src/app/harbor/shipyard/ships.tsx index 037a7f4b..b1fc048a 100644 --- a/src/app/harbor/shipyard/ships.tsx +++ b/src/app/harbor/shipyard/ships.tsx @@ -53,7 +53,7 @@ export default function Ships({ const timeAgo = new TimeAgo('en-US') - console.log("WK NAMES", selectedShip?.wakatimeProjectNames) + console.log('WK NAMES', selectedShip?.wakatimeProjectNames) useEffect(() => { getSession().then((sesh) => setSession(sesh)) @@ -273,7 +273,7 @@ export default function Ships({ !stagedShips.find( (stagedShip) => stagedShip.wakatimeProjectNames.join(',') === - s.wakatimeProjectNames.join(',') + s.wakatimeProjectNames.join(','), ) ? (