Skip to content

Commit ebcec8e

Browse files
committed
Merge remote-tracking branch 'base/main'
2 parents f981b33 + 545cf75 commit ebcec8e

5 files changed

+180
-33
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use server'
2+
3+
import { getGroup } from '@/lib/api'
4+
5+
export async function getGroupInfoAction(groupId: string) {
6+
'use server'
7+
return getGroup(groupId)
8+
}
+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { getGroupInfoAction } from '@/app/groups/add-group-by-url-button-actions'
2+
import { saveRecentGroup } from '@/app/groups/recent-groups-helpers'
3+
import { Button } from '@/components/ui/button'
4+
import { Input } from '@/components/ui/input'
5+
import {
6+
Popover,
7+
PopoverContent,
8+
PopoverTrigger,
9+
} from '@/components/ui/popover'
10+
import { useMediaQuery } from '@/lib/hooks'
11+
import { Loader2, Plus } from 'lucide-react'
12+
import { useState } from 'react'
13+
14+
type Props = {
15+
reload: () => void
16+
}
17+
18+
export function AddGroupByUrlButton({ reload }: Props) {
19+
const isDesktop = useMediaQuery('(min-width: 640px)')
20+
const [url, setUrl] = useState('')
21+
const [error, setError] = useState(false)
22+
const [open, setOpen] = useState(false)
23+
const [pending, setPending] = useState(false)
24+
25+
return (
26+
<Popover open={open} onOpenChange={setOpen}>
27+
<PopoverTrigger asChild>
28+
<Button variant="secondary">
29+
{/* <Plus className="w-4 h-4 mr-2" /> */}
30+
<>Add by URL</>
31+
</Button>
32+
</PopoverTrigger>
33+
<PopoverContent
34+
align={isDesktop ? 'end' : 'start'}
35+
className="[&_p]:text-sm flex flex-col gap-3"
36+
>
37+
<h3 className="font-bold">Add a group by URL</h3>
38+
<p>
39+
If a group was shared with you, you can paste its URL here to add it
40+
to your list.
41+
</p>
42+
<form
43+
className="flex gap-2"
44+
onSubmit={async (event) => {
45+
event.preventDefault()
46+
const [, groupId] =
47+
url.match(
48+
new RegExp(`${window.location.origin}/groups/([^/]+)`),
49+
) ?? []
50+
setPending(true)
51+
const group = groupId ? await getGroupInfoAction(groupId) : null
52+
setPending(false)
53+
if (!group) {
54+
setError(true)
55+
} else {
56+
saveRecentGroup({ id: group.id, name: group.name })
57+
reload()
58+
setUrl('')
59+
setOpen(false)
60+
}
61+
}}
62+
>
63+
<Input
64+
type="url"
65+
required
66+
placeholder="https://spliit.app/..."
67+
className="flex-1 text-base"
68+
value={url}
69+
disabled={pending}
70+
onChange={(event) => {
71+
setUrl(event.target.value)
72+
setError(false)
73+
}}
74+
/>
75+
<Button size="icon" type="submit" disabled={pending}>
76+
{pending ? (
77+
<Loader2 className="w-4 h-4 animate-spin" />
78+
) : (
79+
<Plus className="w-4 h-4" />
80+
)}
81+
</Button>
82+
</form>
83+
{error && (
84+
<p className="text-destructive">
85+
Oops, we are not able to find the group from the URL you provided…
86+
</p>
87+
)}
88+
</PopoverContent>
89+
</Popover>
90+
)
91+
}

src/app/groups/page.tsx

+1-16
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { RecentGroupList } from '@/app/groups/recent-group-list'
22
import { TrackPage } from '@/components/track-page'
3-
import { Button } from '@/components/ui/button'
4-
import { Plus } from 'lucide-react'
53
import { Metadata } from 'next'
6-
import Link from 'next/link'
74

85
export const metadata: Metadata = {
96
title: 'Recently visited groups',
@@ -13,19 +10,7 @@ export default async function GroupsPage() {
1310
return (
1411
<>
1512
<TrackPage path="/groups" />
16-
<div className="flex justify-between items-center gap-4">
17-
<h1 className="font-bold text-2xl">
18-
<Link href="/groups">My groups</Link>
19-
</h1>
20-
<Button asChild size="icon">
21-
<Link href="/groups/create">
22-
<Plus className="w-4 h-4" />
23-
</Link>
24-
</Button>
25-
</div>
26-
<div>
27-
<RecentGroupList />
28-
</div>
13+
<RecentGroupList />
2914
</>
3015
)
3116
}

src/app/groups/recent-group-list.tsx

+51-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client'
22
import { getGroupsAction } from '@/app/groups/actions'
3+
import { AddGroupByUrlButton } from '@/app/groups/add-group-by-url-button'
34
import {
45
RecentGroups,
56
getArchivedGroups,
@@ -10,7 +11,7 @@ import { Button } from '@/components/ui/button'
1011
import { getGroups } from '@/lib/api'
1112
import { Loader2 } from 'lucide-react'
1213
import Link from 'next/link'
13-
import { SetStateAction, useEffect, useState } from 'react'
14+
import { PropsWithChildren, SetStateAction, useEffect, useState } from 'react'
1415
import { RecentGroupListCard } from './recent-group-list-card'
1516

1617
export type RecentGroupsState =
@@ -54,7 +55,7 @@ function sortGroups(
5455
export function RecentGroupList() {
5556
const [state, setState] = useState<RecentGroupsState>({ status: 'pending' })
5657

57-
useEffect(() => {
58+
function loadGroups() {
5859
const groupsInStorage = getRecentGroups()
5960
const starredGroups = getStarredGroups()
6061
const archivedGroups = getArchivedGroups()
@@ -73,35 +74,43 @@ export function RecentGroupList() {
7374
archivedGroups,
7475
})
7576
})
77+
}
78+
79+
useEffect(() => {
80+
loadGroups()
7681
}, [])
7782

7883
if (state.status === 'pending') {
7984
return (
80-
<p>
81-
<Loader2 className="w-4 m-4 mr-2 inline animate-spin" /> Loading recent
82-
groups…
83-
</p>
85+
<GroupsPage reload={loadGroups}>
86+
<p>
87+
<Loader2 className="w-4 m-4 mr-2 inline animate-spin" /> Loading
88+
recent groups…
89+
</p>
90+
</GroupsPage>
8491
)
8592
}
8693

8794
if (state.groups.length === 0) {
8895
return (
89-
<div className="text-sm space-y-2">
90-
<p>You have not visited any group recently.</p>
91-
<p>
92-
<Button variant="link" asChild className="-m-4">
93-
<Link href={`/groups/create`}>Create one</Link>
94-
</Button>{' '}
95-
or ask a friend to send you the link to an existing one.
96-
</p>
97-
</div>
96+
<GroupsPage reload={loadGroups}>
97+
<div className="text-sm space-y-2">
98+
<p>You have not visited any group recently.</p>
99+
<p>
100+
<Button variant="link" asChild className="-m-4">
101+
<Link href={`/groups/create`}>Create one</Link>
102+
</Button>{' '}
103+
or ask a friend to send you the link to an existing one.
104+
</p>
105+
</div>
106+
</GroupsPage>
98107
)
99108
}
100109

101110
const { starredGroupInfo, groupInfo, archivedGroupInfo } = sortGroups(state)
102111

103112
return (
104-
<>
113+
<GroupsPage reload={loadGroups}>
105114
{starredGroupInfo.length > 0 && (
106115
<>
107116
<h2 className="mb-2">Starred groups</h2>
@@ -132,7 +141,7 @@ export function RecentGroupList() {
132141
</div>
133142
</>
134143
)}
135-
</>
144+
</GroupsPage>
136145
)
137146
}
138147

@@ -158,3 +167,28 @@ function GroupList({
158167
</ul>
159168
)
160169
}
170+
171+
function GroupsPage({
172+
children,
173+
reload,
174+
}: PropsWithChildren<{ reload: () => void }>) {
175+
return (
176+
<>
177+
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-2">
178+
<h1 className="font-bold text-2xl flex-1">
179+
<Link href="/groups">My groups</Link>
180+
</h1>
181+
<div className="flex gap-2">
182+
<AddGroupByUrlButton reload={reload} />
183+
<Button asChild>
184+
<Link href="/groups/create">
185+
{/* <Plus className="w-4 h-4 mr-2" /> */}
186+
<>Create</>
187+
</Link>
188+
</Button>
189+
</div>
190+
</div>
191+
<div>{children}</div>
192+
</>
193+
)
194+
}

src/app/groups/recent-groups-page.tsx

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use client'
2+
import { AddGroupByUrlButton } from '@/app/groups/add-group-by-url-button'
3+
import { RecentGroupList } from '@/app/groups/recent-group-list'
4+
import { Button } from '@/components/ui/button'
5+
import Link from 'next/link'
6+
7+
export function RecentGroupsPage() {
8+
return (
9+
<>
10+
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-2">
11+
<h1 className="font-bold text-2xl flex-1">
12+
<Link href="/groups">My groups</Link>
13+
</h1>
14+
<div className="flex gap-2">
15+
<AddGroupByUrlButton reload={() => {}} />
16+
<Button asChild>
17+
<Link href="/groups/create">
18+
{/* <Plus className="w-4 h-4 mr-2" /> */}
19+
<>Create</>
20+
</Link>
21+
</Button>
22+
</div>
23+
</div>
24+
<div>
25+
<RecentGroupList />
26+
</div>
27+
</>
28+
)
29+
}

0 commit comments

Comments
 (0)