Skip to content

Commit

Permalink
feat: ✨ added browser notification for reminders with repetition at i…
Browse files Browse the repository at this point in the history
…ntervals
  • Loading branch information
singhAmandeep007 committed Oct 3, 2024
1 parent cc98a6b commit 8dabb1b
Show file tree
Hide file tree
Showing 23 changed files with 1,411 additions and 54 deletions.
510 changes: 510 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@reduxjs/toolkit": "^2.2.3",
Expand Down
61 changes: 37 additions & 24 deletions src/components/DateTimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from "react";
import { format, set } from "date-fns";
import { Clock } from "lucide-react";

import { cn } from "shared";
import { Input, Label } from "components";

import { Calendar, TCalendarProps } from "./Calendar";
Expand All @@ -12,10 +13,16 @@ const TimeField = ({
time,
onChange,
disabled = false,
classNames,
}: {
time: TTime;
onChange?: (value: TTime) => void;
disabled?: boolean;
classNames?: {
container?: string;
input?: string;
label?: string;
};
}) => {
const handleChange = React.useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -27,16 +34,21 @@ const TimeField = ({
);

return (
<div className="flex flex-col gap-2">
<Label htmlFor="time">Select time :</Label>
<div className={cn("flex flex-col gap-2", classNames?.container)}>
<Label
htmlFor="time"
className={classNames?.label}
>
Select time :
</Label>
<div className="relative">
<div className="pointer-events-none absolute inset-y-0 end-0 top-0 flex items-center pe-3.5">
<Clock size={16} />
</div>
<Input
id="time"
type="time"
className="block min-w-[calc(100%-1rem)] max-md:flex"
className={cn("block min-w-[calc(100%-1rem)] max-md:flex", classNames?.input)}
value={time}
onChange={handleChange}
disabled={disabled}
Expand Down Expand Up @@ -97,29 +109,30 @@ export function DateTimePicker({

return (
<div className=" flex flex-col gap-4">
<div className="flex flex-col gap-2">
<Calendar
showOutsideDays={false}
mode="single"
selected={selectedDateTime}
// @ts-ignore
onSelect={handleDateChange}
defaultMonth={selectedDateTime ? selectedDateTime : new Date()}
initialFocus
required
fromDate={new Date()}
<Calendar
showOutsideDays={false}
mode="single"
selected={selectedDateTime}
// @ts-ignore
onSelect={handleDateChange}
defaultMonth={selectedDateTime ? selectedDateTime : new Date()}
initialFocus
required
fromDate={new Date()}
disabled={isDisabled()}
className="p-0"
{...props}
/>
{withTime && selectedDateTime && (
<TimeField
time={format(selectedDateTime, "HH:mm") as TTime}
onChange={handleTimeChange}
disabled={isDisabled()}
className="p-0"
{...props}
classNames={{
label: "text-primary",
}}
/>
{withTime && selectedDateTime && (
<TimeField
time={format(selectedDateTime, "HH:mm") as TTime}
onChange={handleTimeChange}
disabled={isDisabled()}
/>
)}
</div>
)}

{typeof children === "function" && children({ selectedDateTime })}
</div>
Expand Down
151 changes: 151 additions & 0 deletions src/components/Select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import * as React from "react";
import * as SelectPrimitive from "@radix-ui/react-select";
import { Check, ChevronDown, ChevronUp } from "lucide-react";

import { cn } from "shared";

const Select = SelectPrimitive.Root;

const SelectGroup = SelectPrimitive.Group;

const SelectValue = SelectPrimitive.Value;

const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronDown className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;

const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton
ref={ref}
className={cn("flex cursor-default items-center justify-center py-1", className)}
{...props}
>
<ChevronUp className="h-4 w-4" />
</SelectPrimitive.ScrollUpButton>
));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;

const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton
ref={ref}
className={cn("flex cursor-default items-center justify-center py-1", className)}
{...props}
>
<ChevronDown className="h-4 w-4" />
</SelectPrimitive.ScrollDownButton>
));
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;

const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
)}
position={position}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
"p-1",
position === "popper" &&
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
));
SelectContent.displayName = SelectPrimitive.Content.displayName;

const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
{...props}
/>
));
SelectLabel.displayName = SelectPrimitive.Label.displayName;

const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>

<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
));
SelectItem.displayName = SelectPrimitive.Item.displayName;

const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;

export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
SelectScrollUpButton,
SelectScrollDownButton,
};
18 changes: 11 additions & 7 deletions src/components/ValueSetter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export type TValueSetterProps = {
max?: number;
min?: number;
children?: React.ReactNode;
className?: string;
classNames?: {
container?: string;
value?: string;
controls?: string;
};
testIds?: {
increment?: string;
decrement?: string;
Expand All @@ -25,7 +29,7 @@ export function ValueSetter({
children,
min = 0,
max = 59,
className,
classNames,
testIds,
}: TValueSetterProps) {
const [value, setValue] = useState(initialValue);
Expand All @@ -42,15 +46,15 @@ export function ValueSetter({
}, [value, onChange]);

return (
<div className={cn("flex w-max items-center justify-between gap-4 p-2", className)}>
<div className="flex min-w-12 flex-col items-center justify-center">
<span className="text-4xl font-bold text-primary">{value}</span>
<div className={cn("flex w-max items-center justify-between gap-4 p-2", classNames?.container)}>
<div className={cn("flex min-w-12 flex-col items-center justify-center")}>
<span className={cn("text-4xl font-bold text-primary", classNames?.value)}>{value}</span>
{children}
</div>
<div className="flex flex-col justify-between">
<Button
onClick={increment}
className="rounded-b-none"
className={cn("rounded-b-none", classNames?.controls)}
size={"icon"}
disabled={value >= max}
variant={"outline"}
Expand All @@ -60,7 +64,7 @@ export function ValueSetter({
</Button>
<Button
onClick={decrement}
className="rounded-t-none"
className={cn("text rounded-t-none", classNames?.controls)}
size={"icon"}
disabled={value <= min}
variant={"outline"}
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export * from "./Sonner";
export * from "./Progress";
export * from "./Separator";
export * from "./ValueSetter";
export * from "./Select";
1 change: 1 addition & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./useOnClickOutside";
export * from "./useBreakpoint";
export * from "./useMultiStep";
export * from "./useBrowserNotification";
Loading

0 comments on commit 8dabb1b

Please sign in to comment.