a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Feature/all day dates (#98)

* add all day dates

* styled all day button

---------

Co-authored-by: celine <celine@hyperlink.academy>

authored by

Jared Pereira
celine
and committed by
GitHub
21990895 b076d88f

+99 -20
+5 -1
app/globals.css
··· 172 172 background-color: transparent; 173 173 } 174 174 175 - .input-border { 175 + .input-with-border { 176 176 @apply border; 177 177 @apply border-border; 178 + @apply bg-bg-page; 178 179 @apply rounded-md; 179 180 @apply px-1; 180 181 @apply py-0.5; 181 182 @apply hover:border-tertiary; 182 183 @apply active:border-tertiary; 184 + @apply disabled:border-border-light; 185 + @apply disabled:bg-border-light; 186 + @apply disabled:text-tertiary; 183 187 } 184 188 185 189 .block-border {
+53 -17
components/Blocks/DateTimeBlock.tsx
··· 8 8 import { useUIState } from "src/useUIState"; 9 9 import { setHours, setMinutes } from "date-fns"; 10 10 import { Separator } from "react-aria-components"; 11 + import { Checkbox } from "components/Checkbox"; 11 12 12 13 export function DateTimeBlock(props: BlockProps) { 13 14 let { rep } = useReplicache(); 14 15 let { permissions } = useEntitySetContext(); 15 16 let dateFact = useEntity(props.entityID, "block/date-time"); 16 17 17 - const [timeValue, setTimeValue] = useState<string>("00:00"); 18 + const [timeValue, setTimeValue] = useState<string>( 19 + () => 20 + `${new Date().getHours().toString().padStart(2, "0")}:${new Date().getMinutes().toString().padStart(2, "0")}`, 21 + ); 18 22 let selectedDate = useMemo(() => { 19 23 if (!dateFact) return new Date(); 20 24 return new Date(dateFact.data.value); ··· 36 40 const newSelectedDate = setHours(setMinutes(selectedDate, minutes), hours); 37 41 rep?.mutate.assertFact({ 38 42 entity: props.entityID, 39 - data: { type: "string", value: newSelectedDate.toISOString() }, 43 + data: { 44 + type: "date-time", 45 + value: newSelectedDate.toISOString(), 46 + dateOnly: dateFact?.data.dateOnly, 47 + }, 40 48 attribute: "block/date-time", 41 49 }); 42 50 setTimeValue(time); ··· 47 55 if (date) 48 56 rep?.mutate.assertFact({ 49 57 entity: props.entityID, 50 - data: { type: "string", value: date.toISOString() }, 58 + data: { 59 + type: "date-time", 60 + value: date.toISOString(), 61 + dateOnly: dateFact?.data.dateOnly, 62 + }, 51 63 attribute: "block/date-time", 52 64 }); 53 65 return; ··· 65 77 66 78 rep?.mutate.assertFact({ 67 79 entity: props.entityID, 68 - data: { type: "string", value: newDate.toISOString() }, 80 + data: { type: "date-time", value: newDate.toISOString() }, 69 81 attribute: "block/date-time", 70 82 }); 71 83 }; ··· 92 104 year: "numeric", 93 105 day: "numeric", 94 106 })}{" "} 95 - |{" "} 96 - {selectedDate.toLocaleTimeString(undefined, { 97 - hour: "numeric", 98 - minute: "numeric", 99 - })} 107 + {!dateFact.data.dateOnly ? ( 108 + <span> 109 + |{" "} 110 + {selectedDate.toLocaleTimeString(undefined, { 111 + hour: "numeric", 112 + minute: "numeric", 113 + })} 114 + </span> 115 + ) : null} 100 116 </div> 101 117 ) : ( 102 118 <div ··· 108 124 </div> 109 125 } 110 126 > 111 - <div className=" flex flex-col gap-2 "> 127 + <div className="flex flex-col gap-3 "> 112 128 <DayPicker 113 129 components={{ 114 130 Chevron: (props: ChevronProps) => <CustomChevron {...props} />, ··· 124 140 chevron: "text-inherit", 125 141 month_grid: "w-full table-fixed", 126 142 weekdays: "text-secondary text-sm", 127 - selected: "bg-accent-1 text-accent-2 rounded-md font-bold ", 143 + selected: "!bg-accent-1 text-accent-2 rounded-md font-bold", 128 144 129 145 day: "h-[34px] text-center rounded-md sm:hover:bg-border-light", 130 146 outside: "text-border", ··· 135 151 onSelect={handleDaySelect} 136 152 /> 137 153 <Separator className="border-border" /> 138 - <input 139 - type="time" 140 - value={timeValue} 141 - onChange={handleTimeChange} 142 - className="dateBlockTimeInput input-border bg-bg-page text-primary w-full mb-1 " 143 - /> 154 + <div className="flex gap-4 pb-1 items-center"> 155 + <Checkbox 156 + checked={!!dateFact?.data.dateOnly} 157 + onChange={(e) => { 158 + if (!dateFact) return; 159 + rep?.mutate.assertFact({ 160 + entity: props.entityID, 161 + data: { 162 + type: "date-time", 163 + value: dateFact.data.value, 164 + dateOnly: e.currentTarget.checked, 165 + }, 166 + attribute: "block/date-time", 167 + }); 168 + }} 169 + > 170 + All day 171 + </Checkbox> 172 + <input 173 + disabled={dateFact?.data.dateOnly} 174 + type="time" 175 + value={timeValue} 176 + onChange={handleTimeChange} 177 + className="dateBlockTimeInput input-with-border bg-bg-page text-primary w-full " 178 + /> 179 + </div> 144 180 </div> 145 181 </Popover> 146 182 );
+32
components/Checkbox.tsx
··· 1 + import { CheckboxChecked, CheckboxEmpty } from "./Icons"; 2 + 3 + export function Checkbox(props: { 4 + checked: boolean; 5 + onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; 6 + children: React.ReactNode; 7 + checkboxEmptyClassName?: string; 8 + checkboxCheckedClassName?: string; 9 + }) { 10 + return ( 11 + <label 12 + className={`flex gap-2 items-start cursor-pointer shrink-0 ${props.checked ? "text-primary font-bold " : " text-tertiary font-normal"}`} 13 + > 14 + <input 15 + type="checkbox" 16 + checked={props.checked} 17 + className="hidden" 18 + onChange={(e) => props.onChange(e)} 19 + /> 20 + {!props.checked ? ( 21 + <CheckboxEmpty 22 + className={`shrink-0 mt-[6px] text-tertiary ${props.checkboxEmptyClassName}`} 23 + /> 24 + ) : ( 25 + <CheckboxChecked 26 + className={`shrink-0 mt-[6px] text-accent-contrast ${props.checkboxCheckedClassName}`} 27 + /> 28 + )} 29 + {props.children} 30 + </label> 31 + ); 32 + }
+6 -1
src/replicache/attributes.ts
··· 57 57 cardinality: "one", 58 58 }, 59 59 "block/date-time": { 60 - type: "string", 60 + type: "date-time", 61 61 cardinality: "one", 62 62 }, 63 63 "block/text": { ··· 195 195 type: "spatial-reference"; 196 196 position: { x: number; y: number }; 197 197 value: string; 198 + }; 199 + "date-time": { 200 + type: "date-time"; 201 + value: string; 202 + dateOnly?: boolean; 198 203 }; 199 204 "ordered-reference": { 200 205 type: "ordered-reference";
+3 -1
src/replicache/mutations.ts
··· 313 313 } 314 314 }; 315 315 316 - type FactInput = Omit<Fact<keyof typeof Attributes>, "id"> & { id?: string }; 316 + type FactInput = { 317 + [k in keyof typeof Attributes]: Omit<Fact<k>, "id"> & { id?: string }; 318 + }[keyof typeof Attributes]; 317 319 const assertFact: Mutation<FactInput | Array<FactInput>> = async ( 318 320 args, 319 321 ctx,