Skip to content

Commit

Permalink
Frontend for sources update (#204)
Browse files Browse the repository at this point in the history
* query to fetch minutes per source;

* updated endpoint to return only user's active sources;
frontend update using sources with minutes endpoint;

* added 2x modifier to minutes;
  • Loading branch information
danzjamz authored Sep 6, 2024
1 parent 013dc78 commit bf227b7
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 25 deletions.
2 changes: 2 additions & 0 deletions packages/app/src/api/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ export const pulseKeys = {
['deepWork', startDate, endDate] as const,
categoryTimeOverview: (startDate: string, endDate: string) =>
['categoryTimeOverview', startDate, endDate] as const,
sourcesMinutes: (startDate: string, endDate: string) =>
['sourcesMinutes', startDate, endDate] as const,
}
13 changes: 13 additions & 0 deletions packages/app/src/api/pulse.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ export function useGetSources() {
})
}

export function useGetSourcesWithMinutes(startDate: string, endDate: string) {
const queryFn = () =>
apiRequest({
url: `${BASE_API_URL}/pulses/sourcesMinutes?startDate=${startDate}&endDate=${endDate}`,
method: 'GET',
})
return useBetterQuery<CodeClimbers.SourceWithMinutes[], Error>({
queryKey: pulseKeys.sourcesMinutes(startDate, endDate),
queryFn,
refetchOnWindowFocus: true,
})
}

export function useExportPulses() {
const exportPulses = useCallback(async () => {
try {
Expand Down
50 changes: 50 additions & 0 deletions packages/app/src/components/Home/Source/SourceTimeChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { LinearProgress, Typography, useTheme } from '@mui/material'
import Grid2 from '@mui/material/Unstable_Grid2/Grid2'

interface SourceTimeChartProps {
color: string
time: string
progress: number
}

export const SourceTimeChart = ({
color,
progress,
time,
}: SourceTimeChartProps) => {
const theme = useTheme()

return (
<Grid2
container
justifyContent="space-between"
gap={3}
alignItems="center"
width="100%"
>
<Grid2 sx={{ flex: 1, width: '100%' }}>
<LinearProgress
variant="determinate"
value={progress > 100 ? 100 : progress}
sx={{
alignSelf: 'center',
width: '100%',
backgroundColor: 'transparent',
height: 12,
'& .MuiLinearProgress-bar': {
bottom: 0,
top: 'auto',
backgroundColor: color,
height: 12,
},
}}
/>
</Grid2>
<Grid2>
<Typography variant="body1" color={theme.palette.grey[300]}>
{time}
</Typography>
</Grid2>
</Grid2>
)
}
76 changes: 61 additions & 15 deletions packages/app/src/components/Home/Source/Sources.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from 'react'
import {
Button,
Card,
Expand All @@ -6,42 +7,81 @@ import {
Typography,
useTheme,
} from '@mui/material'
import { LoadingButton } from '@mui/lab'
import SaveAltOutlinedIcon from '@mui/icons-material/SaveAltOutlined'
import AddIcon from '@mui/icons-material/Add'
import { useExportPulses, useGetSources } from '../../../api/pulse.api'
import dayjs from 'dayjs'

import {
useExportPulses,
useGetSourcesWithMinutes,
} from '../../../api/pulse.api'
import {
SourceDetails,
supportedSources,
} from '../../../utils/supportedSources'
import { useState } from 'react'
import SourcesEmpty from './Sources.empty'
import SourcesError from './Sources.error'
import SourcesLoading from './Sources.loading'
import { LoadingButton } from '@mui/lab'
import AddSources from './AddSources'
import { getTimeSince } from '../../../utils/time'
import { minutesToHours } from '../Time/utils'
import { SourceTimeChart } from './SourceTimeChart'

interface SourceRowProps {
source: SourceDetails
lastActive: string
minutes: number
}

const SourceRow = ({ source, lastActive }: SourceRowProps) => {
const SourceRow = ({ source, lastActive, minutes }: SourceRowProps) => {
const theme = useTheme()
const compareTime = 90

return (
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Stack direction="row" alignItems="center" spacing={1}>
<Stack
direction="row"
alignItems="center"
justifyContent="space-between"
width="100%"
>
<Stack direction="row" alignItems="center" spacing={1} width="100%">
<img
alt={source.displayName + ' Logo'}
src={source.logo}
style={{ height: '32px', width: '32px' }}
/>
<Stack direction="column">
<Stack direction="column" width="100%">
<Typography variant="body2" fontWeight={700}>
{source.displayName}
</Typography>
<Typography variant="body2" fontWeight={400}>
{`Last pulse ${getTimeSince(lastActive)}`}
</Typography>
{minutes > 0 && (
<SourceTimeChart
time={minutesToHours(minutes)}
progress={Math.floor((minutes / compareTime) * 100)}
color={theme.palette.graphColors.blue}
/>
)}
<Stack direction="row" justifyContent="space-between">
{minutes === 0 && lastActive && (
<Typography
variant="body2"
fontWeight={400}
color={theme.palette.grey[300]}
>
{`Last pulse ${getTimeSince(lastActive)}`}
</Typography>
)}
{minutes === 0 && (
<Typography
variant="body1"
fontWeight={400}
color={theme.palette.grey[300]}
>
0m
</Typography>
)}
</Stack>
</Stack>
</Stack>
</Stack>
Expand All @@ -50,11 +90,15 @@ const SourceRow = ({ source, lastActive }: SourceRowProps) => {

const Sources = () => {
const {
data: connectedSources,
data: sourcesWithMinutes,
isPending,
isEmpty,
isError,
} = useGetSources()
} = useGetSourcesWithMinutes(
dayjs().startOf('day').toISOString(),
dayjs().endOf('day').toISOString(),
)

const { exportPulses } = useExportPulses()
const [exportingPulses, setExportingPulses] = useState(false)
const [addSourcesOpen, setAddSourcesOpen] = useState(false)
Expand All @@ -78,7 +122,7 @@ const Sources = () => {

return (
<>
<Card sx={{ boxShadow: 'none', borderRadius: 0, minWidth: 262, flex: 1 }}>
<Card sx={{ boxShadow: 'none', borderRadius: 0, minWidth: 335, flex: 1 }}>
<CardContent sx={{ padding: '24px', height: '100%', display: 'flex' }}>
<Stack direction="column" justifyContent={'space-between'} flex={1}>
<div>
Expand Down Expand Up @@ -106,9 +150,10 @@ const Sources = () => {
</Button>
</Stack>
<Stack direction="column" marginTop="24px" gap={3}>
{connectedSources.map((source, index) => {
{sourcesWithMinutes.map((source, index) => {
const sourceDetails = supportedSources.find(
(supportedSource) => supportedSource.name === source.name,
(supportedSource) =>
supportedSource.name.includes(source.name),
)

if (sourceDetails) {
Expand All @@ -117,6 +162,7 @@ const Sources = () => {
key={index}
source={sourceDetails}
lastActive={source.lastActive}
minutes={source.minutes}
/>
)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/Home/Time/TimeDataChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const TimeDataChart = ({
return <Box sx={{ position: 'relative' }}>{progressBars}</Box>
}
return (
<Grid2 container justifyContent="space-between" gap={3} alignItems="center">
<Grid2 container justifyContent="space-between" gap={3}>
<Grid2 sx={{ minWidth: 120 }}>
<Typography variant="body1">{title}</Typography>
</Grid2>
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/utils/supportedSources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const supportedSources: SourceDetails[] = [
`,
},
{
name: 'chrome-code_climbers',
name: 'chrome',
displayName: 'Chromium Browser',
logo: chromeLogo,
link: 'https://chromewebstore.google.com/detail/code-climbers/fdmoefklpgbjapealpjfailnmalbgpbe',
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/utils/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ dayjs.updateLocale('en', {
mm: '%dm',
h: '1h',
hh: '%dh',
d: '1D',
dd: '%dD',
d: '1d',
dd: '%dd',
M: '1M',
MM: '%dM',
y: '1Y',
Expand Down
6 changes: 6 additions & 0 deletions packages/server/src/types/activities.api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ declare namespace CodeClimbers {
name: string
lastActive: string
}

export interface SourceWithMinutes {
name: string
lastActive: string
minutes: number
}
}
3 changes: 2 additions & 1 deletion packages/server/src/types/time.api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ declare namespace CodeClimbers {
}

export interface SourceMinutes {
source: string
name: string
minutes: number
lastActive: string
}

export interface SourcesOverviewDao {
Expand Down
26 changes: 21 additions & 5 deletions packages/server/src/v1/activities/activities.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,28 @@ export class ActivitiesService {
startDate: string,
endDate: string,
): Promise<CodeClimbers.SourceMinutes[]> {
const sources = await this.pulseRepo.getSourcesMinutes(startDate, endDate)
const userSources = await this.getSources()
const sourcesWithMinutes = await this.pulseRepo.getSourcesMinutes(
startDate,
endDate,
)

return Object.keys(sourcesWithMinutes)
.map((key) => {
const lastActive =
userSources.find((source) =>
source.name.toLowerCase().includes(key.toLowerCase()),
)?.lastActive ?? null

if (lastActive === null) return null

return Object.keys(sources).map((key) => ({
source: key,
minutes: sources[key],
}))
return {
name: key,
minutes: sourcesWithMinutes[key] * 2,
lastActive,
}
})
.filter((item) => item !== null)
}

async getDeepWork(
Expand Down

0 comments on commit bf227b7

Please sign in to comment.