mirror of
https://github.com/hex248/sprint.git
synced 2026-02-07 18:23:03 +00:00
calendar QoL changes
This commit is contained in:
@@ -243,6 +243,7 @@ export function SprintForm({
|
|||||||
<PopoverContent className="w-auto p-0" align="center">
|
<PopoverContent className="w-auto p-0" align="center">
|
||||||
<Calendar
|
<Calendar
|
||||||
mode="single"
|
mode="single"
|
||||||
|
currentSprint={{ colour, startDate, endDate }}
|
||||||
selected={startDate}
|
selected={startDate}
|
||||||
onSelect={(value) => {
|
onSelect={(value) => {
|
||||||
if (!value) return;
|
if (!value) return;
|
||||||
@@ -250,6 +251,9 @@ export function SprintForm({
|
|||||||
}}
|
}}
|
||||||
autoFocus
|
autoFocus
|
||||||
sprints={calendarSprints}
|
sprints={calendarSprints}
|
||||||
|
showWeekNumber
|
||||||
|
showOutsideDays={false}
|
||||||
|
defaultMonth={startDate}
|
||||||
/>
|
/>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
@@ -266,6 +270,7 @@ export function SprintForm({
|
|||||||
<PopoverContent className="w-auto p-0" align="center">
|
<PopoverContent className="w-auto p-0" align="center">
|
||||||
<Calendar
|
<Calendar
|
||||||
mode="single"
|
mode="single"
|
||||||
|
currentSprint={{ colour, startDate, endDate }}
|
||||||
selected={endDate}
|
selected={endDate}
|
||||||
onSelect={(value) => {
|
onSelect={(value) => {
|
||||||
if (!value) return;
|
if (!value) return;
|
||||||
@@ -274,6 +279,9 @@ export function SprintForm({
|
|||||||
autoFocus
|
autoFocus
|
||||||
sprints={calendarSprints}
|
sprints={calendarSprints}
|
||||||
isEnd
|
isEnd
|
||||||
|
showWeekNumber
|
||||||
|
showOutsideDays={false}
|
||||||
|
defaultMonth={endDate}
|
||||||
/>
|
/>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Button, buttonVariants } from "@/components/ui/button";
|
|||||||
import Icon from "@/components/ui/icon";
|
import Icon from "@/components/ui/icon";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
function Calendar({
|
export function Calendar({
|
||||||
className,
|
className,
|
||||||
classNames,
|
classNames,
|
||||||
showOutsideDays = true,
|
showOutsideDays = true,
|
||||||
@@ -15,11 +15,13 @@ function Calendar({
|
|||||||
components,
|
components,
|
||||||
sprints,
|
sprints,
|
||||||
isEnd,
|
isEnd,
|
||||||
|
currentSprint,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DayPicker> & {
|
}: React.ComponentProps<typeof DayPicker> & {
|
||||||
buttonVariant?: React.ComponentProps<typeof Button>["variant"];
|
buttonVariant?: React.ComponentProps<typeof Button>["variant"];
|
||||||
sprints?: SprintRecord[];
|
sprints?: SprintRecord[];
|
||||||
isEnd?: boolean;
|
isEnd?: boolean;
|
||||||
|
currentSprint?: { colour: string; startDate: Date; endDate: Date };
|
||||||
}) {
|
}) {
|
||||||
const defaultClassNames = getDefaultClassNames();
|
const defaultClassNames = getDefaultClassNames();
|
||||||
|
|
||||||
@@ -112,7 +114,9 @@ function Calendar({
|
|||||||
|
|
||||||
return <Icon icon="chevronDownIcon" className={cn("size-4", className)} {...props} />;
|
return <Icon icon="chevronDownIcon" className={cn("size-4", className)} {...props} />;
|
||||||
},
|
},
|
||||||
DayButton: (props) => <CalendarDayButton {...props} sprints={sprints} isEnd={isEnd} />,
|
DayButton: (props) => (
|
||||||
|
<CalendarDayButton {...props} sprints={sprints} isEnd={isEnd} currentSprint={currentSprint} />
|
||||||
|
),
|
||||||
WeekNumber: ({ children, ...props }) => {
|
WeekNumber: ({ children, ...props }) => {
|
||||||
return (
|
return (
|
||||||
<td {...props}>
|
<td {...props}>
|
||||||
@@ -129,7 +133,7 @@ function Calendar({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CalendarDayButton({
|
export function CalendarDayButton({
|
||||||
className,
|
className,
|
||||||
day,
|
day,
|
||||||
modifiers,
|
modifiers,
|
||||||
@@ -137,8 +141,13 @@ function CalendarDayButton({
|
|||||||
style,
|
style,
|
||||||
disabled,
|
disabled,
|
||||||
isEnd,
|
isEnd,
|
||||||
|
currentSprint,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof DayButton> & { sprints?: SprintRecord[]; isEnd?: boolean }) {
|
}: React.ComponentProps<typeof DayButton> & {
|
||||||
|
sprints?: SprintRecord[];
|
||||||
|
isEnd?: boolean;
|
||||||
|
currentSprint?: { colour: string; startDate: Date; endDate: Date };
|
||||||
|
}) {
|
||||||
const defaultClassNames = getDefaultClassNames();
|
const defaultClassNames = getDefaultClassNames();
|
||||||
|
|
||||||
const ref = React.useRef<HTMLButtonElement>(null);
|
const ref = React.useRef<HTMLButtonElement>(null);
|
||||||
@@ -172,11 +181,47 @@ function CalendarDayButton({
|
|||||||
"flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal",
|
"flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal",
|
||||||
"[&>span]:text-xs [&>span]:opacity-70",
|
"[&>span]:text-xs [&>span]:opacity-70",
|
||||||
!sprint?.color && "hover:bg-primary/90 hover:text-foreground",
|
!sprint?.color && "hover:bg-primary/90 hover:text-foreground",
|
||||||
"data-[selected-single=true]:!bg-foreground data-[selected-single=true]:!text-background data-[selected-single=true]:hover:!bg-foreground/90",
|
!currentSprint?.startDate &&
|
||||||
|
"data-[selected-single=true]:!bg-foreground data-[selected-single=true]:!text-background data-[selected-single=true]:hover:!bg-foreground/90",
|
||||||
"data-[range-start=true]:!bg-foreground data-[range-start=true]:!text-background",
|
"data-[range-start=true]:!bg-foreground data-[range-start=true]:!text-background",
|
||||||
"data-[range-middle=true]:!bg-foreground data-[range-middle=true]:!text-background",
|
"data-[range-middle=true]:!bg-foreground data-[range-middle=true]:!text-background",
|
||||||
"data-[range-end=true]:!bg-foreground data-[range-end=true]:!text-background",
|
"data-[range-end=true]:!bg-foreground data-[range-end=true]:!text-background",
|
||||||
|
|
||||||
sprint?.color && "border-t border-b !border-(--sprint-color) !bg-(--sprint-color)/5",
|
sprint?.color && "border-t border-b !border-(--sprint-color) !bg-(--sprint-color)/5",
|
||||||
|
|
||||||
|
// part of new sprint
|
||||||
|
currentSprint?.startDate &&
|
||||||
|
currentSprint?.endDate &&
|
||||||
|
day.date >= currentSprint?.startDate &&
|
||||||
|
day.date <= currentSprint?.endDate &&
|
||||||
|
"!border-t !border-b !border-(--current-sprint-color) !bg-(--current-sprint-color)/5 hover:!bg-(--current-sprint-color)/50 border-dashed",
|
||||||
|
|
||||||
|
// is start of new sprint
|
||||||
|
currentSprint?.startDate &&
|
||||||
|
day.date.getDate() === currentSprint?.startDate.getDate() &&
|
||||||
|
day.date.getMonth() === currentSprint?.startDate.getMonth() &&
|
||||||
|
"!border-l !border-(--current-sprint-color)",
|
||||||
|
|
||||||
|
// is start of new sprint
|
||||||
|
currentSprint?.endDate &&
|
||||||
|
day.date.getDate() === currentSprint?.endDate.getDate() &&
|
||||||
|
day.date.getMonth() === currentSprint?.endDate.getMonth() &&
|
||||||
|
"!border-r !border-(--current-sprint-color)",
|
||||||
|
|
||||||
|
// is selected
|
||||||
|
"data-[selected-single=true]:!bg-(--current-sprint-color)/75 data-[selected-single=true]:hover:!bg-(--current-sprint-color)/60",
|
||||||
|
|
||||||
|
// is start and after end date (disable)
|
||||||
|
!isEnd &&
|
||||||
|
currentSprint?.endDate &&
|
||||||
|
day.date > currentSprint?.endDate &&
|
||||||
|
"opacity-50 pointer-events-none cursor-not-allowed",
|
||||||
|
// isEnd and before start date (disable)
|
||||||
|
isEnd &&
|
||||||
|
currentSprint?.startDate &&
|
||||||
|
day.date < currentSprint?.startDate &&
|
||||||
|
"opacity-50 pointer-events-none cursor-not-allowed",
|
||||||
|
|
||||||
defaultClassNames.day,
|
defaultClassNames.day,
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
@@ -184,6 +229,7 @@ function CalendarDayButton({
|
|||||||
{
|
{
|
||||||
...style,
|
...style,
|
||||||
"--sprint-color": sprint?.color ? sprint.color : null,
|
"--sprint-color": sprint?.color ? sprint.color : null,
|
||||||
|
"--current-sprint-color": currentSprint?.colour ? currentSprint.colour : null,
|
||||||
borderLeft:
|
borderLeft:
|
||||||
sprint && day.date.getUTCDate() === new Date(sprint.startDate).getUTCDate()
|
sprint && day.date.getUTCDate() === new Date(sprint.startDate).getUTCDate()
|
||||||
? `1px solid ${sprint?.color}`
|
? `1px solid ${sprint?.color}`
|
||||||
@@ -203,5 +249,3 @@ function CalendarDayButton({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Calendar, CalendarDayButton };
|
|
||||||
|
|||||||
16
todo.md
16
todo.md
@@ -1,19 +1,19 @@
|
|||||||
# HIGH PRIORITY
|
# HIGH PRIORITY
|
||||||
|
|
||||||
- BUGS:
|
|
||||||
- date picker opens at today's date instead of the selected date
|
|
||||||
- january: date picker is above, february: date picker is below (likely due to how many rows worth of sprints are displayed) - -my-1/-m-px on dates that have a sprint
|
|
||||||
- FEATURES:
|
- FEATURES:
|
||||||
- issues
|
- issues
|
||||||
- issue type (options stored on Organisation)
|
- issue type (options stored on Organisation)
|
||||||
- filters
|
- filters
|
||||||
|
- time tracking:
|
||||||
# LOW PRIORITY
|
- add overlay in the bottom left for active timers if there are any. this should be minimal with the issue key (API-005), the time, and a play/pause + end button
|
||||||
|
|
||||||
- setup guide
|
|
||||||
- pricing page
|
- pricing page
|
||||||
- see jira and other competitors
|
- see jira and other competitors
|
||||||
- explore payment providers (stripe is the only one i know)
|
- explore payment providers (stripe is the only one i know)
|
||||||
|
|
||||||
|
# LOW PRIORITY
|
||||||
|
|
||||||
|
- disable self-hosting stuff
|
||||||
|
- make closed source
|
||||||
- dedicated /register route (currently login/register are combined on /login)
|
- dedicated /register route (currently login/register are combined on /login)
|
||||||
- real logo
|
- real logo
|
||||||
- org settings
|
- org settings
|
||||||
@@ -26,8 +26,6 @@
|
|||||||
- deadline
|
- deadline
|
||||||
- comments
|
- comments
|
||||||
- admins are capable of deleting comments from members who are at their permission level or below (not sure if this should apply, or if ANYONE should have control over others' comments - people in an org tend to be trusted to not be trolls)
|
- admins are capable of deleting comments from members who are at their permission level or below (not sure if this should apply, or if ANYONE should have control over others' comments - people in an org tend to be trusted to not be trolls)
|
||||||
- time tracking:
|
|
||||||
- add overlay in the bottom left for active timers if there are any. this should be minimal with the issue key (API-005), the time, and a play/pause + end button
|
|
||||||
- user preferences
|
- user preferences
|
||||||
- colour scheme
|
- colour scheme
|
||||||
- "assign to me by default" option for new issues
|
- "assign to me by default" option for new issues
|
||||||
|
|||||||
Reference in New Issue
Block a user