Skip to content

Commit 6875ba1

Browse files
Merge pull request #255 from daostack/common-detail-layout
Fetch common discussions added.
2 parents e2ffade + 6ff48ef commit 6875ba1

File tree

28 files changed

+404
-184
lines changed

28 files changed

+404
-184
lines changed
Lines changed: 32 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,42 @@
11
import React from "react";
2+
import { Discussion } from "../../../../../shared/models";
3+
import { getDaysAgo, getUserName } from "../../../../../shared/utils";
24
import "./index.scss";
35

4-
export default function DiscussionsComponent() {
6+
interface DiscussionsComponentProps {
7+
discussions: Discussion[];
8+
}
9+
10+
export default function DiscussionsComponent({ discussions }: DiscussionsComponentProps) {
11+
const date = new Date();
512
return (
613
<div className="discussions-component-wrapper">
7-
<div className="discussion-item-wrapper">
8-
<div className="discussion-top-bar">
9-
<div className="img-wrapper">
10-
<img src="https://picsum.photos/40/40" alt="kek" />
11-
</div>
12-
<div className="creator-information">
13-
<div className="name">Peter Parkey</div>
14-
<div className="days-ago">3 days ago</div>
15-
</div>
16-
</div>
17-
<div className="discussion-content">
18-
<div className="title">How about planting trees in india as well?</div>
19-
<div className="description">
20-
I was thinking we should do some work on this and expand to new forests. They need us and our trees. Mother
21-
Nature does a lot of tree planting ably aided by the wind, rain, and critters, both feathered and furry.
22-
However, she would probably appreciate some assistance from us, humans.
23-
</div>
24-
<div className="read-more">Read More</div>
25-
<div className="line"></div>
26-
</div>
27-
<div className="bottom-content">
28-
<div className="discussion-count">
29-
<img src="/icons/discussions.svg" alt="discussions" />
30-
<div className="count">123</div>
31-
</div>
32-
<div className="view-all-discussions">View discussions</div>
33-
</div>
34-
</div>
35-
<div className="discussion-item-wrapper">
36-
<div className="discussion-top-bar">
37-
<div className="img-wrapper">
38-
<img src="https://picsum.photos/40/40" alt="kek" />
39-
</div>
40-
<div className="creator-information">
41-
<div className="name">Peter Parkey</div>
42-
<div className="days-ago">3 days ago</div>
43-
</div>
44-
</div>
45-
<div className="discussion-content">
46-
<div className="title">How about planting trees in india as well?</div>
47-
<div className="description">
48-
I was thinking we should do some work on this and expand to new forests. They need us and our trees. Mother
49-
Nature does a lot of tree planting ably aided by the wind, rain, and critters, both feathered and furry.
50-
However, she would probably appreciate some assistance from us, humans.
51-
</div>
52-
<div className="read-more">Read More</div>
53-
<div className="line"></div>
54-
</div>
55-
<div className="bottom-content">
56-
<div className="discussion-count">
57-
<img src="/icons/discussions.svg" alt="discussions" />
58-
<div className="count">123</div>
14+
{discussions.map((d) => (
15+
<div className="discussion-item-wrapper" key={d.id}>
16+
<div className="discussion-top-bar">
17+
<div className="img-wrapper">
18+
<img src={d.owner?.photoURL} alt={getUserName(d.owner)} />
19+
</div>
20+
<div className="creator-information">
21+
<div className="name">{getUserName(d.owner)}</div>
22+
<div className="days-ago">{getDaysAgo(date, d.createTime)} </div>
23+
</div>
24+
</div>
25+
<div className="discussion-content">
26+
<div className="title">{d.title}</div>
27+
<div className="description">{d.message}</div>
28+
{/* <div className="read-more">Read More</div> */}
29+
<div className="line"></div>
30+
</div>
31+
<div className="bottom-content">
32+
<div className="discussion-count">
33+
<img src="/icons/discussions.svg" alt="discussions" />
34+
<div className="count">{d.discussionMessage?.length || 0}</div>
35+
</div>
36+
{(d?.discussionMessage?.length || 0) > 0 && <div className="view-all-discussions">View discussions</div>}
5937
</div>
60-
<div className="view-all-discussions">View discussions</div>
6138
</div>
62-
</div>
39+
))}
6340
</div>
6441
);
6542
}

packages/web/src/containers/Common/components/CommonDetailContainer/DiscussionsComponent/index.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,16 @@
1010
margin-bottom: 24px;
1111
.img-wrapper {
1212
margin-right: 16px;
13+
width: 40px;
14+
height: 40px;
15+
position: relative;
1316
img {
17+
position: absolute;
18+
right: 0;
19+
bottom: 0;
20+
width: 100%;
21+
height: 100%;
22+
object-fit: cover;
1423
border-radius: 50%;
1524
}
1625
}
Lines changed: 98 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
import React, { useEffect, useMemo, useState } from "react";
1+
import React, { useCallback, useEffect, useMemo, useState } from "react";
22
import { useSelector, useDispatch } from "react-redux";
33
import { useParams } from "react-router-dom";
4+
import { Modal } from "../../../../shared/components/Modal";
5+
import { useModal } from "../../../../shared/hooks";
46
import { formatPrice } from "../../../../shared/utils";
57
import {
68
AboutTabComponent,
79
PreviewInformationList,
810
DiscussionsComponent,
911
} from "../../components/CommonDetailContainer";
10-
import { getCommonDetail } from "../../store/actions";
11-
import { selectCommonDetail, selectProposals, selectDiscussions } from "../../store/selectors";
12+
import { getCommonDetail, loadCommonDiscussionList } from "../../store/actions";
13+
import {
14+
selectCommonDetail,
15+
selectProposals,
16+
selectDiscussions,
17+
selectIsDiscussionsLoaded,
18+
} from "../../store/selectors";
1219
import "./index.scss";
1320
interface CommonDetailRouterParams {
1421
id: string;
@@ -35,11 +42,13 @@ const tabs = [
3542

3643
export default function CommonDetail() {
3744
const { id } = useParams<CommonDetailRouterParams>();
38-
const [tab, setTab] = useState("discussions");
39-
const common = useSelector(selectCommonDetail);
40-
const proposals = useSelector(selectProposals);
41-
const discussions = useSelector(selectDiscussions);
45+
const [tab, setTab] = useState("about");
46+
const common = useSelector(selectCommonDetail());
47+
const proposals = useSelector(selectProposals());
48+
const discussions = useSelector(selectDiscussions());
49+
const isDiscussionsLoaded = useSelector(selectIsDiscussionsLoaded());
4250
const dispatch = useDispatch();
51+
const { isShowing, onOpen, onClose } = useModal(false);
4352

4453
useEffect(() => {
4554
dispatch(getCommonDetail.request(id));
@@ -63,80 +72,102 @@ export default function CommonDetail() {
6372
[discussions],
6473
);
6574

75+
const changeTabHandler = useCallback(
76+
(tab: string) => {
77+
switch (tab) {
78+
case "discussions":
79+
if (!isDiscussionsLoaded) {
80+
dispatch(loadCommonDiscussionList.request());
81+
}
82+
break;
83+
84+
default:
85+
break;
86+
}
87+
setTab(tab);
88+
},
89+
[dispatch, isDiscussionsLoaded],
90+
);
91+
6692
return (
6793
common && (
68-
<div className="common-detail-wrapper">
69-
<div className="main-information-block">
70-
<div className="main-information-wrapper">
71-
<div className="img-wrapper">
72-
<img src={common?.image} alt={common?.name} />
73-
</div>
74-
<div className="text-information-wrapper">
75-
<div className="text">
76-
<div className="name">{common?.name}</div>
77-
<div className="tagline">{common?.metadata.byline}</div>
94+
<>
95+
<Modal isShowing={isShowing} onClose={onClose}>
96+
<div>hello</div>
97+
</Modal>
98+
<div className="common-detail-wrapper">
99+
<div className="main-information-block">
100+
<div className="main-information-wrapper">
101+
<div className="img-wrapper">
102+
<img src={common?.image} alt={common?.name} />
78103
</div>
79-
<div className="numbers">
80-
<div className="item">
81-
<div className="value">{formatPrice(common?.balance)}</div>
82-
<div className="name">Available Funds</div>
104+
<div className="text-information-wrapper">
105+
<div className="text">
106+
<div className="name">{common?.name}</div>
107+
<div className="tagline">{common?.metadata.byline}</div>
83108
</div>
84-
<div className="item">
85-
<div className="value">{formatPrice(common?.raised)}</div>
86-
<div className="name">Total Raised</div>
109+
<div className="numbers">
110+
<div className="item" onClick={onOpen}>
111+
<div className="value">{formatPrice(common?.balance)}</div>
112+
<div className="name">Available Funds</div>
113+
</div>
114+
<div className="item">
115+
<div className="value">{formatPrice(common?.raised)}</div>
116+
<div className="name">Total Raised</div>
117+
</div>
118+
<div className="item">
119+
<div className="value">{common?.members.length}</div>
120+
<div className="name">Members</div>
121+
</div>
122+
<div className="item">
123+
<div className="value">0</div>
124+
<div className="name">Active Proposals</div>
125+
</div>
87126
</div>
88-
<div className="item">
89-
<div className="value">{common?.members.length}</div>
90-
<div className="name">Members</div>
127+
</div>
128+
<div className="line"></div>
129+
<div className="common-content-selector">
130+
<div className="tabs-wrapper">
131+
{tabs.map((t) => (
132+
<div
133+
key={t.key}
134+
className={`tab-item ${tab === t.key ? "active" : ""}`}
135+
onClick={() => changeTabHandler(t.key)}
136+
>
137+
{t.name}
138+
{tab === t.key && <span></span>}
139+
</div>
140+
))}
91141
</div>
92-
<div className="item">
93-
<div className="value">0</div>
94-
<div className="name">Active Proposals</div>
142+
<div className="social-wrapper">
143+
<button className="button-blue">Join the effort</button>
95144
</div>
96145
</div>
97146
</div>
98-
<div className="line"></div>
99-
<div className="common-content-selector">
100-
<div className="tabs-wrapper">
101-
{tabs.map((t) => (
102-
<div
103-
key={t.key}
104-
className={`tab-item ${tab === t.key ? "active" : ""}`}
105-
onClick={() => setTab(t.key)}
106-
>
107-
{t.name}
108-
{tab === t.key && <span></span>}
109-
</div>
110-
))}
147+
</div>
148+
<div className="main-content-container">
149+
<div className="tab-title">{tab}</div>
150+
<div className="inner-main-content-wrapper">
151+
<div className="tab-content-wrapper">
152+
{tab === "about" && <AboutTabComponent common={common} />}
153+
{tab === "discussions" && <DiscussionsComponent discussions={discussions} />}
111154
</div>
112-
<div className="social-wrapper">
113-
<button className="button-blue">Join the effort</button>
155+
<div className="sidebar-wrapper">
156+
<PreviewInformationList
157+
title="Latest Discussions"
158+
data={latestDiscussions}
159+
vievAllHandler={() => setTab("discussions")}
160+
/>
161+
<PreviewInformationList
162+
title="Latest Proposals"
163+
data={lastestProposals}
164+
vievAllHandler={() => setTab("proposals")}
165+
/>
114166
</div>
115167
</div>
116168
</div>
117169
</div>
118-
<div className="main-content-container">
119-
<div className="tab-title">{tab}</div>
120-
<div className="inner-main-content-wrapper">
121-
<div className="tab-content-wrapper">
122-
{tab === "about" && <AboutTabComponent common={common} />}
123-
{tab === "discussions" && <DiscussionsComponent />}
124-
</div>
125-
<div className="sidebar-wrapper">
126-
<PreviewInformationList
127-
title="Latest Discussions"
128-
data={latestDiscussions}
129-
vievAllHandler={() => setTab("discussions")}
130-
/>
131-
<PreviewInformationList
132-
title="Latest Proposals"
133-
data={lastestProposals}
134-
vievAllHandler={() => setTab("proposals")}
135-
/>
136-
</div>
137-
</div>
138-
</div>
139-
</div>
170+
</>
140171
)
141172
);
142173
}

packages/web/src/containers/Common/containers/CommonListContainer/CommonListContainer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ const options = {
1616
};
1717

1818
export default function CommonListContainer() {
19-
const commons = useSelector(selectCommonList);
20-
const page = useSelector(selectCurrentPage);
19+
const commons = useSelector(selectCommonList());
20+
const page = useSelector(selectCurrentPage());
2121
const dispatch = useDispatch();
2222
const loader = useRef(null);
2323

packages/web/src/containers/Common/interfaces/CommonsStateType.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export interface CommonsStateType {
66
page: number;
77
proposals: Proposal[];
88
discussions: Discussion[];
9+
isDiscussionsLoaded: boolean;
910
}

packages/web/src/containers/Common/store/actions.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,9 @@ export const updatePage = createStandardAction(CommonsActionTypes.UPDATE_PAGE)<n
2020
export const setDiscussion = createStandardAction(CommonsActionTypes.SET_DISCUSSION)<Discussion[]>();
2121

2222
export const setProposals = createStandardAction(CommonsActionTypes.SET_PROPOSALS)<Proposal[]>();
23+
24+
export const loadCommonDiscussionList = createAsyncAction(
25+
CommonsActionTypes.LOAD_COMMON_DISCUSSIONS,
26+
CommonsActionTypes.LOAD_COMMON_DISCUSSIONS_SUCCESS,
27+
CommonsActionTypes.LOAD_COMMON_DISCUSSIONS_FAILURE,
28+
)<void, Discussion[], Error>();

packages/web/src/containers/Common/store/constants.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@ export enum CommonsActionTypes {
1212
SET_DISCUSSION = "@COMMONS/SET_DISCUSSIONS",
1313

1414
SET_PROPOSALS = "@COMMONS/SET_PROPOSALS",
15+
16+
LOAD_COMMON_DISCUSSIONS = "@COMMONS/LOAD_COMMON_DISCUSSIONS",
17+
LOAD_COMMON_DISCUSSIONS_SUCCESS = "@COMMONS/LOAD_COMMON_DISCUSSIONS_SUCCESS",
18+
LOAD_COMMON_DISCUSSIONS_FAILURE = "@COMMONS/LOAD_COMMON_DISCUSSIONS_FAILURE",
1519
}

packages/web/src/containers/Common/store/reducer.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const initialState: CommonsStateType = {
99
page: 1,
1010
proposals: [],
1111
discussions: [],
12+
isDiscussionsLoaded: false,
1213
};
1314

1415
type Action = ActionType<typeof actions>;
@@ -38,6 +39,12 @@ const reducer = createReducer<CommonsStateType, Action>(initialState)
3839
produce(state, (nextState) => {
3940
nextState.proposals = action.payload;
4041
}),
42+
)
43+
.handleAction(actions.loadCommonDiscussionList.success, (state, action) =>
44+
produce(state, (nextState) => {
45+
nextState.discussions = action.payload;
46+
nextState.isDiscussionsLoaded = true;
47+
}),
4148
);
4249

4350
export default reducer;

0 commit comments

Comments
 (0)