Skip to content

Commit

Permalink
sprint index
Browse files Browse the repository at this point in the history
  • Loading branch information
JensRavens committed Dec 12, 2024
1 parent da4de35 commit f2b3cd4
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 0 deletions.
7 changes: 7 additions & 0 deletions app/javascript/util/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ export class Formatter {
}).format(Number(value));
}

singleDigitNumber(value: number): string {
return new Intl.NumberFormat(this.locale, {
minimumFractionDigits: 1,
maximumFractionDigits: 1,
}).format(value);
}

date(value: Date | string): string | null {
const date = this.parseDate(value);

Expand Down
File renamed without changes.
29 changes: 29 additions & 0 deletions app/views/sprints/index.props.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
render "components/current_user"

field :sprints, array: true, value: -> { @sprints } do
field :id
field :title
field :sprint_from, Time
field :sprint_until, Time

field :performances, array: true, value: -> { sprint_feedbacks } do
field :id
field :review_notes, null: true
field :working_day_count, Integer
field :holiday_count, Integer
field :sick_day_count, Integer
field :daily_nerd_count, Integer, value: -> { daily_nerd_count.to_i }
field :tracked_hours, Float
field :billable_hours, Float
field :billable_per_day, Float
field :retro_rating, Integer, null: true
field :finished_storypoints, Integer
field :revenue, Float, null: true, value: -> { revenue if helpers.policy(sprint).show_revenue? }

field :user do
field :id
field :display_name
end
end
end
field :next_page_url, null: true, value: -> { helpers.path_to_next_page @sprints }
107 changes: 107 additions & 0 deletions app/views/sprints/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React from 'react';
import { Sidebar } from '../../javascript/components/sidebar/sidebar';
import { PageProps } from '../../../data.d';
import { useFormatter, useTranslate } from '../../javascript/util/dependencies';
import { Layout } from '../../javascript/components/layout/layout';
import { Stack } from '../../javascript/components/stack/stack';
import { Text } from '../../javascript/components/text/text';
import { Card } from '../../javascript/components/card/card';
import { Button } from '../../javascript/components/button/button';
import { useModal } from '../../javascript/components/modal/modal';
import { useReaction } from '../../javascript/sprinkles/reaction';

export default function ({
data: { currentUser, sprints, nextPageUrl },
}: PageProps<'sprints/index'>): JSX.Element {
const t = useTranslate();
const l = useFormatter();
const reaction = useReaction();
const modal = useModal();

return (
<Layout user={currentUser} container>
<Stack>
<Stack line="mobile" justify="space-between">
<Text type="headline">{t('users.index.title')}</Text>
<Button title="add" onClick={() => modal.present('/sprints/new')} />
</Stack>
<Stack>
{sprints.map((sprint) => (
<Card
key={sprint.id}
title={sprint.title}
icon="🏃"
subtitle={l.dateRange(sprint.sprintFrom, sprint.sprintUntil)}
>
<table className="table">
<thead>
<tr>
<th></th>
<th>Daily Nerd</th>
<th>Tracked</th>
<th>Billable</th>
<th>Retro</th>
<th>Storypoints</th>
<th>Turnover</th>
</tr>
</thead>
<tbody>
{sprint.performances.map((performance) => (
<tr key={performance.id}>
<td>
{performance.user.displayName}
<br />
{performance.workingDayCount}/{performance.holidayCount}
/{performance.sickDayCount}
</td>
<td>{performance.dailyNerdCount}</td>
<td>
{l.singleDigitNumber(performance.trackedHours)}
<br />
{l.singleDigitNumber(
performance.trackedHours / performance.workingDayCount
)}
/day
</td>
<td>
{l.singleDigitNumber(performance.billableHours)}
<br />
{l.singleDigitNumber(
performance.billableHours /
performance.workingDayCount
)}
/day
</td>
<td>{performance.retroRating}</td>
<td>
{performance.finishedStorypoints}
<br />
{l.singleDigitNumber(
performance.finishedStorypoints /
performance.workingDayCount
)}
/day
</td>
<td>{l.currency(performance.revenue)}</td>
</tr>
))}
</tbody>
</table>
</Card>
))}
{nextPageUrl && (
<Button
title="more"
onClick={() =>
reaction.history.extendPageContentWithPagination(
nextPageUrl,
'sprints'
)
}
/>
)}
</Stack>
</Stack>
</Layout>
);
}
32 changes: 32 additions & 0 deletions data.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,38 @@ export interface DataSchema {
users: Array<{ id: string; displayName: string }>;
defaultMonth: string;
};
'sprints/index': {
currentUser: {
id: string;
displayName: string;
avatarUrl: string;
};
sprints: Array<{
id: string;
title: string;
sprintFrom: string;
sprintUntil: string;
performances: Array<{
id: string;
reviewNotes: string | null;
workingDayCount: number;
holidayCount: number;
sickDayCount: number;
dailyNerdCount: number;
trackedHours: number;
billableHours: number;
billablePerDay: number;
retroRating: number | null;
finishedStorypoints: number;
revenue: number | null;
user: {
id: string;
displayName: string;
};
}>;
}>;
nextPageUrl: string | null;
};
'users/index': {
currentUser: {
id: string;
Expand Down

0 comments on commit f2b3cd4

Please sign in to comment.