Skip to content

Commit

Permalink
Merge pull request #583 from marchhq/refac/this-week-inbox-expand
Browse files Browse the repository at this point in the history
feat: add item on this week (item add component for this week and inbox)
  • Loading branch information
sajdakabir authored Nov 14, 2024
2 parents 8d9811d + 1a04ef2 commit cfa30db
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 16 deletions.
4 changes: 2 additions & 2 deletions apps/frontend/src/components/Inbox/InboxPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import { ItemAdd } from "@/src/components/atoms/ItemAdd"
import { ItemExpandModal } from "@/src/components/atoms/ItemExpandModal"
import { InboxAddItem } from "@/src/components/Inbox/InboxAddItem"
import { InboxItems } from "@/src/components/Inbox/InboxItems"
import { useCycleItemStore } from "@/src/lib/store/cycle.store"
import classNames from "@/src/utils/classNames"
Expand Down Expand Up @@ -29,7 +29,7 @@ export const InboxPage: React.FC = () => {
</div>
</header>
<div className="flex flex-col gap-5">
<InboxAddItem />
<ItemAdd />
<InboxItems />
</div>
</div>
Expand Down
20 changes: 10 additions & 10 deletions apps/frontend/src/components/ThisWeek/ThisWeekItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ export const ThisWeekItems: React.FC<ThisWeekItemsProps> = ({

const { session } = useAuth()

useEffect(() => {
setWeekDates(startDate, endDate)
}, [startDate, endDate, setWeekDates])

useEffect(() => {
fetchThisWeek(session, startDate, endDate)
}, [session, fetchThisWeek, startDate, endDate])

useEffect(() => {}, [items])

const handleExpand = (item: CycleItem) => {
setCurrentItem(item)
}
Expand Down Expand Up @@ -149,16 +159,6 @@ export const ThisWeekItems: React.FC<ThisWeekItemsProps> = ({
dateChanged,
])

useEffect(() => {
setWeekDates(startDate, endDate)
}, [startDate, endDate, setWeekDates])

useEffect(() => {
fetchThisWeek(session, startDate, endDate)
}, [session, fetchThisWeek, startDate, endDate])

useEffect(() => {}, [items])

return (
<div>
<div className="flex flex-col gap-2.5 text-sm">
Expand Down
7 changes: 4 additions & 3 deletions apps/frontend/src/components/ThisWeek/ThisWeekPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React, { useState } from "react"
import { addWeeks } from "date-fns"

import { ThisWeekArrows } from "./ThisWeekArrows"
import { ItemAdd } from "@/src/components/atoms/ItemAdd"
import { ItemExpandModal } from "@/src/components/atoms/ItemExpandModal"
import { ThisWeekItems } from "@/src/components/ThisWeek/ThisWeekItems"
import { CycleItem } from "@/src/lib/@types/Items/Cycle"
Expand Down Expand Up @@ -58,14 +59,13 @@ export const ThisWeekPage: React.FC = () => {

return (
<div className="flex h-full w-[calc(100%-160px)]">
<div className="relative flex flex-auto flex-col gap-12">
<div className="relative flex flex-auto flex-col gap-5">
<header>
<div className="flex flex-1 flex-col gap-4 pl-5 text-sm text-foreground">
<div className="flex w-full items-center justify-between gap-5">
<div className="flex items-center gap-2 text-secondary-foreground">
<span className="text-secondary-foreground">
{todoAndNullItemsLength} todo / {inProgressItems.length} in
progress / {doneItems.length} done / {items.length} total
{todoAndNullItemsLength} / {items.length} completed
</span>
<span>
{items.length > 0
Expand All @@ -85,6 +85,7 @@ export const ThisWeekPage: React.FC = () => {
</div>
</div>
</header>
<ItemAdd />
<ThisWeekItems startDate={startDate} endDate={endDate} />
<ItemExpandModal />
</div>
Expand Down
115 changes: 115 additions & 0 deletions apps/frontend/src/components/atoms/ItemAdd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
"use client"

import React, { useState, useEffect, useRef } from "react"

import { useAuth } from "@/src/contexts/AuthContext"
import { CycleItem } from "@/src/lib/@types/Items/Cycle"
import { useCycleItemStore } from "@/src/lib/store/cycle.store"
import { isLink } from "@/src/utils/helpers"

export const ItemAdd: React.FC = () => {
const { session } = useAuth()

const textareaRefTitle = useRef<HTMLTextAreaElement>(null)
const [addingItem, setAddingItem] = useState(false)
const [title, setTitle] = useState("")

const { createItem, error } = useCycleItemStore()

useEffect(() => {
const textarea = textareaRefTitle.current
if (textarea) {
textarea.style.height = "auto"
textarea.style.height = `${textarea.scrollHeight}px`
}
}, [title])

const handleCloseAddItem = async () => {
setAddingItem(false)
setTitle("")
}

const handleAddItem = async () => {
const trimmedTitle = title.trim()

if (!trimmedTitle) {
return
}

const linkDetected = isLink(trimmedTitle)

// prepare the final URL if its a link
const finalTitle =
linkDetected && !/^https:\/\//i.test(trimmedTitle)
? `https://${trimmedTitle}`
: trimmedTitle

// prepare the item data
const data: Partial<CycleItem> = {
title: finalTitle,
type: linkDetected ? "link" : "issue",
}

if (linkDetected) {
data.metadata = {
url: finalTitle,
}
}

await createItem(session, data)

setAddingItem(false)
setTitle("")
}

const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (!addingItem) {
setAddingItem(true)
}
if (event.key === "Enter") {
event.preventDefault()
if (title) {
handleAddItem()
}
}
}

const handleOnBlur = () => {
handleCloseAddItem()
}

useEffect(() => {
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
if (addingItem) {
e.preventDefault()
}
}

window.addEventListener("beforeunload", handleBeforeUnload)

return () => {
window.removeEventListener("beforeunload", handleBeforeUnload)
}
}, [addingItem])

return (
<div onBlur={handleOnBlur} className="pl-5">
<textarea
ref={textareaRefTitle}
value={title}
onChange={(e) => setTitle(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="add anything..."
className="w-full resize-none overflow-hidden truncate whitespace-pre-wrap break-words bg-background text-sm text-foreground outline-none placeholder:text-secondary-foreground focus:outline-none"
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus
rows={1}
/>
{error && (
<div className="truncate text-xs text-danger-foreground">
<span>{error}</span>
</div>
)}
</div>
)
}
2 changes: 1 addition & 1 deletion apps/frontend/src/lib/store/cycle.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ export const useCycleItemStore = create<ExtendedCycleItemStore>((set, get) => ({
},
thisWeek: {
...state.thisWeek,
items: [...state.thisWeek.items, data.response],
items: [data.response, ...state.thisWeek.items],
isLoading: false,
error: null,
},
Expand Down

0 comments on commit cfa30db

Please sign in to comment.