Skip to content

Commit a2e16ca

Browse files
author
Roshan Jossy
authored
Merge pull request #20 from firstcontributions/user-page
2 parents e321633 + 87ee7df commit a2e16ca

File tree

13 files changed

+1250
-52
lines changed

13 files changed

+1250
-52
lines changed

next.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const nextConfig = {
1111
async rewrites() {
1212
return [
1313
{
14-
source: '/@:handle([a-zA-Z0-9]+)/:id*',
14+
source: '/@:handle([a-zA-Z0-9/-_]+)/:id*',
1515
destination: '/users/:handle/:id*',
1616
},
1717
{

src/components/UserDetails/Bio.tsx

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { useState } from 'react'
2+
import { GoPencil } from '@react-icons/all-files/go/GoPencil'
3+
import { GoCheck } from '@react-icons/all-files/go/GoCheck'
24
import { graphql, useFragment, useMutation } from 'react-relay'
35
import { Bio_user$key } from '../../queries/__generated__/Bio_user.graphql'
46

@@ -18,6 +20,7 @@ const Bio = ({ user }: BioProps) => {
1820
)
1921

2022
const [bio, setBio] = useState(data.bio)
23+
const [editMode, setEditMode] = useState(false)
2124

2225
const [commitMutation, isMutationInFlight] = useMutation(
2326
graphql`
@@ -29,8 +32,10 @@ const Bio = ({ user }: BioProps) => {
2932
}
3033
`
3134
)
32-
const onChange = (evt: any) => setBio(evt.target.value)
35+
const onChange = (evt: React.ChangeEvent<HTMLInputElement>) =>
36+
setBio(evt.target.value)
3337
const onSubmit = () => {
38+
setEditMode(false)
3439
commitMutation({
3540
variables: {
3641
input: { id: data.id, bio: bio },
@@ -39,13 +44,30 @@ const Bio = ({ user }: BioProps) => {
3944
}
4045

4146
return (
42-
<input
43-
onChange={onChange}
44-
onBlur={onSubmit}
45-
className="dark:text-gray-300"
46-
type="text"
47-
defaultValue={data.bio}
48-
/>
47+
<div>
48+
{editMode ? (
49+
<div className="flex justify-between">
50+
<input
51+
onChange={onChange}
52+
onBlur={onSubmit}
53+
className="dark:text-gray-300 dark:bg-dark-600"
54+
type="text"
55+
disabled={isMutationInFlight}
56+
defaultValue={data.bio}
57+
/>
58+
<button onClick={() => setEditMode(false)}>
59+
<GoCheck />
60+
</button>
61+
</div>
62+
) : (
63+
<div className="flex justify-between">
64+
<span>{data.bio}</span>
65+
<button onClick={() => setEditMode(true)}>
66+
<GoPencil />
67+
</button>
68+
</div>
69+
)}
70+
</div>
4971
)
5072
}
5173

src/components/UserDetails/UserDetails.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { graphql, useFragment } from 'react-relay'
22
import BadgeList from './Badges/BadgeList'
33
import type { UserDetails_user$key } from '../../queries/__generated__/UserDetails_user.graphql'
4-
import { useState, ChangeEvent, FormEventHandler } from 'react'
54
import Bio from './Bio'
65
import { GoIssueOpened } from '@react-icons/all-files/go/GoIssueOpened'
76
import { GoGitPullRequest } from '@react-icons/all-files/go/GoGitPullRequest'

src/components/feed/MyStories.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { graphql, usePaginationFragment } from 'react-relay'
2+
import { MyStories__Query$key } from '../../queries/__generated__/MyStories__Query.graphql'
3+
import StoryPreview from './StoryPreview'
4+
5+
type MyStoriesProps = {
6+
user: MyStories__Query$key
7+
}
8+
9+
const MyStories = ({ user }: MyStoriesProps) => {
10+
const { data } = usePaginationFragment(
11+
graphql`
12+
fragment MyStories__Query on User
13+
@refetchable(queryName: "MyStoriesUser_Query")
14+
@argumentDefinitions(
15+
count: { type: "Int", defaultValue: 10 }
16+
cursor: { type: "String" }
17+
) {
18+
stories(first: $count, after: $cursor)
19+
@connection(key: "UserQuery__stories") {
20+
edges {
21+
node {
22+
id
23+
...StoryPreview_node
24+
}
25+
}
26+
}
27+
}
28+
`,
29+
user
30+
)
31+
32+
return (
33+
<>
34+
{data.stories.edges.map(
35+
(edge) => edge && <StoryPreview story={edge?.node} key={edge.node.id} />
36+
)}
37+
</>
38+
)
39+
}
40+
41+
export default MyStories

src/components/story/StoryEditor.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,28 @@ export default function Editor({ editable, body }: EditorProps) {
142142
--tw-prose-pre-code: none;
143143
--tw-prose-pre-bg: none;
144144
}
145+
146+
.dark .ce-inline-tool,
147+
.dark .ce-toolbar__plus,
148+
.dark .ce-toolbar__settings-btn {
149+
@apply text-gray-400;
150+
}
151+
152+
.dark .ce-inline-toolbar,
153+
.dark .ce-conversion-toolbar,
154+
.dark .ce-toolbox,
155+
.dark .ce-popover,
156+
.dark .ce-settings {
157+
@apply bg-dark-600 border-dark-500;
158+
}
159+
160+
.dark .ce-popover__item-icon {
161+
@apply bg-dark-500;
162+
}
163+
164+
.dark .ce-block--selected {
165+
@apply bg-dark-500 text-gray-800;
166+
}
145167
`}
146168
</style>
147169
{editable && <Button onClick={() => handleStorySubmit()}>Submit </Button>}

src/pages/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { NextPage, NextPageContext } from 'next'
1+
import type { NextPageContext } from 'next'
22
import UserDetails from '../components/UserDetails/UserDetails'
33
import { graphql, usePreloadedQuery } from 'react-relay'
44
import { withRelay, RelayProps } from 'relay-nextjs'
@@ -11,6 +11,7 @@ import IssuesFromRecentRepos from '../components/issue/IssuesFromRecentRepo'
1111
import Layout from '../components/Layout'
1212
import Login from '../components/Login'
1313
import Feed from '../components/feed/Feed'
14+
import RelayModernEnvironment from 'relay-runtime/lib/store/RelayModernEnvironment'
1415

1516
const RootQuery = graphql`
1617
query pages_UserQuery {
@@ -56,7 +57,8 @@ const Home = ({
5657
}
5758

5859
export default withRelay(Home, RootQuery, {
59-
createClientEnvironment: () => getClientEnvironment()!,
60+
createClientEnvironment: () =>
61+
getClientEnvironment() as RelayModernEnvironment,
6062
createServerEnvironment: async (ctx: NextPageContext) => {
6163
const { createServerEnvironment } = await import(
6264
'../lib/server/server_environment'

src/pages/story/[id].tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import dynamic from 'next/dynamic'
33
import { graphql, usePreloadedQuery } from 'react-relay'
44
import { RelayProps, withRelay } from 'relay-nextjs'
55
import Layout from '../../components/Layout'
6+
import UserDetails from '../../components/UserDetails/UserDetails'
67
import { getClientEnvironment } from '../../lib/client_environment'
78
import { Id_StoryQuery } from '../../queries/__generated__/Id_StoryQuery.graphql'
89

@@ -16,6 +17,9 @@ const StoryQuery = graphql`
1617
... on Story {
1718
id
1819
contentJson
20+
createdBy {
21+
...UserDetails_user
22+
}
1923
}
2024
}
2125
}
@@ -29,7 +33,13 @@ const Story = ({
2933
<div>
3034
<Layout
3135
sidebarContentRight={<div>Promoted</div>}
32-
sidebarContentLeft={<div>Reactions</div>}
36+
sidebarContentLeft={
37+
<div>
38+
{query.node?.createdBy && (
39+
<UserDetails user={query?.node?.createdBy} />
40+
)}
41+
</div>
42+
}
3343
>
3444
<Editor body={query?.node?.contentJson} editable={false} />
3545
</Layout>

src/pages/users/[handle].tsx

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,56 @@
11
import { useRouter } from 'next/router'
2+
import { NextPageContext } from 'next'
3+
import { graphql, usePreloadedQuery } from 'react-relay'
4+
import { RelayProps, withRelay } from 'relay-nextjs'
5+
import Layout from '../../components/Layout'
6+
import { getClientEnvironment } from '../../lib/client_environment'
7+
import Card from '../../components/Card'
8+
import UserDetails from '../../components/UserDetails/UserDetails'
9+
import RelayModernEnvironment from 'relay-runtime/lib/store/RelayModernEnvironment'
10+
import MyStories from '../../components/feed/MyStories'
11+
import { Handle_UserQuery } from '../../queries/__generated__/Handle_UserQuery.graphql'
212

3-
const User = () => {
13+
const UserQuery = graphql`
14+
query Handle_UserQuery($handle: String!) {
15+
user(handle: $handle) {
16+
handle
17+
...UserDetails_user
18+
...MyStories__Query
19+
}
20+
}
21+
`
22+
23+
const User = ({
24+
preloadedQuery,
25+
}: RelayProps<Record<string, never>, Handle_UserQuery>) => {
26+
const query = usePreloadedQuery(UserQuery, preloadedQuery)
427
const router = useRouter()
528
const { handle } = router.query
629

7-
return <h1>Welcome {handle}</h1>
30+
return (
31+
<div>
32+
<Layout
33+
sidebarContentRight={handle}
34+
sidebarContentLeft={
35+
<Card>
36+
<UserDetails user={query.user} />
37+
</Card>
38+
}
39+
>
40+
<MyStories user={query.user} />
41+
</Layout>
42+
</div>
43+
)
844
}
945

10-
export default User
46+
export default withRelay(User, UserQuery, {
47+
createClientEnvironment: () =>
48+
getClientEnvironment() as RelayModernEnvironment,
49+
createServerEnvironment: async (ctx: NextPageContext) => {
50+
const { createServerEnvironment } = await import(
51+
'../../lib/server/server_environment'
52+
)
53+
54+
return createServerEnvironment(ctx)
55+
},
56+
})

0 commit comments

Comments
 (0)