mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 05:00:43 +10:00
Show user listings in profile
This commit is contained in:
parent
89758e6318
commit
fec0c03bed
4 changed files with 123 additions and 10 deletions
|
|
@ -106,16 +106,56 @@
|
|||
.listingsTitle {
|
||||
@apply --marketplaceH3FontStyles;
|
||||
color: var(--matterColorAnti);
|
||||
margin-bottom: 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@media (--viewportLarge) {
|
||||
margin-top: 19px;
|
||||
}
|
||||
}
|
||||
|
||||
.withBioMissingAbove {
|
||||
/* Avoid extra borders in mobile when bio is missing */
|
||||
border-top: none;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
border-top: 1px solid var(--matterColorNegative);
|
||||
}
|
||||
}
|
||||
|
||||
.listings {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.listing {
|
||||
width: 100%;
|
||||
float: left;
|
||||
|
||||
/* Single column in mobile */
|
||||
margin-top: 34px;
|
||||
&:first-of-type {
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
@media (--viewportMedium) {
|
||||
/* Two columns in desktop */
|
||||
width: calc(50% - 12px);
|
||||
|
||||
/* Horizontal space */
|
||||
&:nth-of-type(odd) {
|
||||
margin-right: 12px;
|
||||
}
|
||||
&:nth-of-type(even) {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
/* Vertical space */
|
||||
margin-top: 41px;
|
||||
&:nth-of-type(1),
|
||||
&:nth-of-type(2) {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,20 @@ export const SHOW_USER_REQUEST = 'app/ProfilePage/SHOW_USER_REQUEST';
|
|||
export const SHOW_USER_SUCCESS = 'app/ProfilePage/SHOW_USER_SUCCESS';
|
||||
export const SHOW_USER_ERROR = 'app/ProfilePage/SHOW_USER_ERROR';
|
||||
|
||||
export const QUERY_LISTINGS_REQUEST = 'app/ProfilePage/QUERY_LISTINGS_REQUEST';
|
||||
export const QUERY_LISTINGS_SUCCESS = 'app/ProfilePage/QUERY_LISTINGS_SUCCESS';
|
||||
export const QUERY_LISTINGS_ERROR = 'app/ProfilePage/QUERY_LISTINGS_ERROR';
|
||||
|
||||
// ================ Reducer ================ //
|
||||
|
||||
const initialState = {
|
||||
userId: null,
|
||||
|
||||
userShowInProgress: false,
|
||||
userShowError: null,
|
||||
|
||||
queryListingsError: null,
|
||||
userListingRefs: [],
|
||||
};
|
||||
|
||||
export default function profilePageReducer(state = initialState, action = {}) {
|
||||
|
|
@ -26,6 +34,13 @@ export default function profilePageReducer(state = initialState, action = {}) {
|
|||
case SHOW_USER_ERROR:
|
||||
return { ...state, userShowInProgress: false, userShowError: payload };
|
||||
|
||||
case QUERY_LISTINGS_REQUEST:
|
||||
return { ...state, userListingRefs: [], queryListingsError: null };
|
||||
case QUERY_LISTINGS_SUCCESS:
|
||||
return { ...state, userListingRefs: payload.listingRefs };
|
||||
case QUERY_LISTINGS_ERROR:
|
||||
return { ...state, queryListingsError: payload };
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
@ -48,11 +63,39 @@ export const showUserError = e => ({
|
|||
payload: e,
|
||||
});
|
||||
|
||||
export const queryListingsRequest = () => ({
|
||||
type: QUERY_LISTINGS_REQUEST,
|
||||
});
|
||||
|
||||
export const queryListingsSuccess = listingRefs => ({
|
||||
type: QUERY_LISTINGS_SUCCESS,
|
||||
payload: { listingRefs },
|
||||
});
|
||||
|
||||
export const queryListingsError = e => ({
|
||||
type: QUERY_LISTINGS_ERROR,
|
||||
error: true,
|
||||
payload: e,
|
||||
});
|
||||
|
||||
// ================ Thunks ================ //
|
||||
|
||||
export const queryUserListings = userId => (dispatch, getState, sdk) => {
|
||||
dispatch(queryListingsRequest());
|
||||
return sdk.listings
|
||||
.query({ author_id: userId, include: ['images'] })
|
||||
.then(response => {
|
||||
// Pick only the id and type properties from the response listings
|
||||
const listingRefs = response.data.data.map(({ id, type }) => ({ id, type }));
|
||||
dispatch(addMarketplaceEntities(response));
|
||||
dispatch(queryListingsSuccess(listingRefs));
|
||||
return response;
|
||||
})
|
||||
.catch(e => dispatch(queryListingsError(storableError(e))));
|
||||
};
|
||||
|
||||
export const showUser = userId => (dispatch, getState, sdk) => {
|
||||
dispatch(showUserRequest(userId));
|
||||
dispatch(fetchCurrentUser());
|
||||
return sdk.users
|
||||
.show({ id: userId, include: ['profileImage'] })
|
||||
.then(response => {
|
||||
|
|
@ -60,5 +103,13 @@ export const showUser = userId => (dispatch, getState, sdk) => {
|
|||
dispatch(showUserSuccess());
|
||||
return response;
|
||||
})
|
||||
.catch(e => showUserError(storableError(e)));
|
||||
.catch(e => dispatch(showUserError(storableError(e))));
|
||||
};
|
||||
|
||||
export const loadData = userId => (dispatch, getState, sdk) => {
|
||||
return Promise.all([
|
||||
dispatch(fetchCurrentUser()),
|
||||
dispatch(showUser(userId)),
|
||||
dispatch(queryUserListings(userId)),
|
||||
]);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ import {
|
|||
Footer,
|
||||
AvatarLarge,
|
||||
NamedLink,
|
||||
ListingCard,
|
||||
} from '../../components';
|
||||
import { TopbarContainer } from '../../containers';
|
||||
import { showUser } from './ProfilePage.duck';
|
||||
import { loadData } from './ProfilePage.duck';
|
||||
import config from '../../config';
|
||||
|
||||
import css from './ProfilePage.css';
|
||||
|
|
@ -36,6 +37,8 @@ export const ProfilePageComponent = props => {
|
|||
user,
|
||||
userShowInProgress,
|
||||
userShowError,
|
||||
queryListingsError,
|
||||
listings,
|
||||
intl,
|
||||
} = props;
|
||||
const ensuredCurrentUser = ensureCurrentUser(currentUser);
|
||||
|
|
@ -44,7 +47,6 @@ export const ProfilePageComponent = props => {
|
|||
ensuredCurrentUser.id && profileUser.id && ensuredCurrentUser.id.uuid === profileUser.id.uuid;
|
||||
const displayName = profileUser.attributes.profile.displayName;
|
||||
const bio = profileUser.attributes.profile.bio;
|
||||
const listings = [];
|
||||
const hasBio = !!bio;
|
||||
const hasListings = listings.length > 0;
|
||||
|
||||
|
|
@ -87,6 +89,13 @@ export const ProfilePageComponent = props => {
|
|||
<h2 className={css.listingsTitle}>
|
||||
<FormattedMessage id="ProfilePage.listingsTitle" values={{ count: listings.length }} />
|
||||
</h2>
|
||||
<ul className={css.listings}>
|
||||
{listings.map(l => (
|
||||
<li className={css.listing} key={l.id.uuid}>
|
||||
<ListingCard listing={l} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
@ -94,7 +103,7 @@ export const ProfilePageComponent = props => {
|
|||
|
||||
let content;
|
||||
|
||||
if (userShowError) {
|
||||
if (userShowError || queryListingsError) {
|
||||
content = (
|
||||
<p className={css.error}>
|
||||
<FormattedMessage id="ProfilePage.loadingDataFailed" />
|
||||
|
|
@ -150,9 +159,10 @@ ProfilePageComponent.defaultProps = {
|
|||
currentUser: null,
|
||||
user: null,
|
||||
userShowError: null,
|
||||
queryListingsError: null,
|
||||
};
|
||||
|
||||
const { bool } = PropTypes;
|
||||
const { bool, arrayOf } = PropTypes;
|
||||
|
||||
ProfilePageComponent.propTypes = {
|
||||
logoutError: propTypes.error,
|
||||
|
|
@ -161,6 +171,8 @@ ProfilePageComponent.propTypes = {
|
|||
user: propTypes.user,
|
||||
userShowInProgress: bool.isRequired,
|
||||
userShowError: propTypes.error,
|
||||
queryListingsError: propTypes.error,
|
||||
listings: arrayOf(propTypes.listing).isRequired,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
|
|
@ -170,9 +182,16 @@ const mapStateToProps = state => {
|
|||
// Page needs logoutError
|
||||
const { logoutError } = state.Auth;
|
||||
const { currentUser } = state.user;
|
||||
const { userId, userShowInProgress, userShowError } = state.ProfilePage;
|
||||
const matches = getMarketplaceEntities(state, [{ type: 'user', id: userId }]);
|
||||
const user = matches.length === 1 ? matches[0] : null;
|
||||
const {
|
||||
userId,
|
||||
userShowInProgress,
|
||||
userShowError,
|
||||
queryListingsError,
|
||||
userListingRefs,
|
||||
} = state.ProfilePage;
|
||||
const userMatches = getMarketplaceEntities(state, [{ type: 'user', id: userId }]);
|
||||
const user = userMatches.length === 1 ? userMatches[0] : null;
|
||||
const listings = getMarketplaceEntities(state, userListingRefs);
|
||||
return {
|
||||
logoutError,
|
||||
scrollingDisabled: isScrollingDisabled(state),
|
||||
|
|
@ -180,6 +199,8 @@ const mapStateToProps = state => {
|
|||
user,
|
||||
userShowInProgress,
|
||||
userShowError,
|
||||
queryListingsError,
|
||||
listings,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -187,7 +208,7 @@ const ProfilePage = compose(connect(mapStateToProps), injectIntl)(ProfilePageCom
|
|||
|
||||
ProfilePage.loadData = params => {
|
||||
const id = new UUID(params.id);
|
||||
return showUser(id);
|
||||
return loadData(id);
|
||||
};
|
||||
|
||||
export default ProfilePage;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ describe('ProfilePage', () => {
|
|||
scrollingDisabled={false}
|
||||
user={createUser('test-user')}
|
||||
userShowInProgress={false}
|
||||
listings={[]}
|
||||
intl={fakeIntl}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue