Skip to content

Commit c24af09

Browse files
committed
fix: fixed reponsiveness issues on mobile view
1 parent c025310 commit c24af09

File tree

5 files changed

+186
-70
lines changed

5 files changed

+186
-70
lines changed

src/profile-v2/CertificateCard.jsx

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33
import { FormattedDate, FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
4-
import { Hyperlink } from '@openedx/paragon';
4+
import { breakpoints, Hyperlink, useWindowSize } from '@openedx/paragon';
55
import get from 'lodash.get';
66

7+
import classNames from 'classnames';
78
import professionalCertificateSVG from './assets/professional-certificate.svg';
89
import verifiedCertificateSVG from './assets/verified-certificate.svg';
910
import messages from './Certificates.messages';
@@ -27,6 +28,8 @@ const CertificateCard = ({
2728
audit: null,
2829
}[certificateType] || null;
2930

31+
const isMobileView = useWindowSize().width <= breakpoints.small.minWidth;
32+
3033
return (
3134
<div
3235
key={`${modifiedDate}-${courseId}`}
@@ -37,24 +40,47 @@ const CertificateCard = ({
3740
className="certificate-type-illustration"
3841
style={{ backgroundImage: `url(${certificateIllustration})` }}
3942
/>
40-
<div className="d-flex flex-column position-relative p-0 width-19625rem">
43+
<div className={classNames(
44+
'd-flex flex-column position-relative p-0',
45+
{ 'max-width-19rem': isMobileView },
46+
{ 'width-19625rem': !isMobileView },
47+
)}
48+
>
4149
<div className="w-100 color-black">
42-
<p className="small mb-0 font-weight-normal">
50+
<p className={classNames([
51+
'mb-0 font-weight-normal',
52+
isMobileView ? 'x-small' : 'small',
53+
])}
54+
>
4355
{intl.formatMessage(get(
4456
messages,
4557
`profile.certificates.types.${certificateType}`,
4658
messages['profile.certificates.types.unknown'],
4759
))}
4860
</p>
49-
<h4 className="m-0 color-black">{courseDisplayName}</h4>
50-
<p className="small mb-0">
61+
<p className={classNames([
62+
'm-0 color-black',
63+
isMobileView ? 'h5' : 'h4',
64+
])}
65+
>
66+
{courseDisplayName}
67+
</p>
68+
<p className={classNames([
69+
'mb-0',
70+
isMobileView ? 'x-small' : 'small',
71+
])}
72+
>
5173
<FormattedMessage
5274
id="profile.certificate.organization.label"
5375
defaultMessage="From"
5476
/>
5577
</p>
5678
<h5 className="mb-0 color-black">{courseOrganization}</h5>
57-
<p className="small mb-0">
79+
<p className={classNames([
80+
'mb-0',
81+
isMobileView ? 'x-small' : 'small',
82+
])}
83+
>
5884
<FormattedMessage
5985
id="profile.certificate.completion.date.label"
6086
defaultMessage="Completed on {date}"
@@ -69,12 +95,20 @@ const CertificateCard = ({
6995
destination={downloadUrl}
7096
target="_blank"
7197
showLaunchIcon={false}
72-
className="btn btn-primary btn-rounded font-weight-normal px-4 py-0625rem"
98+
className={classNames(
99+
'btn btn-primary btn-rounded font-weight-normal px-4 py-0625rem',
100+
{ 'btn-sm': isMobileView },
101+
)}
73102
>
74103
{intl.formatMessage(messages['profile.certificates.view.certificate'])}
75104
</Hyperlink>
76105
</div>
77-
<p className="small mb-0 pt-3">
106+
<p
107+
className={classNames([
108+
'mb-0 pt-3',
109+
isMobileView ? 'x-small' : 'small',
110+
])}
111+
>
78112
<FormattedMessage
79113
id="profile.certificate.uuid"
80114
defaultMessage="Credential ID {certificate_uuid}"
@@ -91,7 +125,8 @@ const CertificateCard = ({
91125

92126
CertificateCard.propTypes = {
93127
certificateType: PropTypes.string,
94-
courseDisplayName: PropTypes.string,
128+
courseDisplayName:
129+
PropTypes.string,
95130
courseOrganization: PropTypes.string,
96131
modifiedDate: PropTypes.string,
97132
downloadUrl: PropTypes.string,

src/profile-v2/Certificates.jsx

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,71 @@ import { FormattedMessage } from '@edx/frontend-platform/i18n';
44
import { connect } from 'react-redux';
55
import { getConfig } from '@edx/frontend-platform';
66

7+
import classNames from 'classnames';
8+
import { breakpoints, useWindowSize } from '@openedx/paragon';
79
import CertificateCard from './CertificateCard';
810
import { certificatesSelector } from './data/selectors';
911

10-
const Certificates = ({ certificates }) => (
11-
<div>
12-
<div className="col justify-content-start align-items-start g-5rem p-0">
13-
<div className="col align-self-stretch height-2625rem justify-content-start align-items-start p-0">
14-
<h2 className="font-weight-bold text-primary-500 m-0">
15-
<FormattedMessage
16-
id="profile.your.certificates"
17-
defaultMessage="Your certificates"
18-
description="heading for the certificates section"
19-
/>
20-
</h2>
12+
const Certificates = ({ certificates }) => {
13+
const isMobileView = useWindowSize().width <= breakpoints.small.minWidth;
14+
const isTabletView = useWindowSize().width <= breakpoints.medium.minWidth;
15+
return (
16+
<div>
17+
<div className="col justify-content-start align-items-start g-5rem p-0">
18+
<div className="col align-self-stretch height-2625rem justify-content-start align-items-start p-0">
19+
<p className={classNames([
20+
'font-weight-bold text-primary-500 m-0',
21+
isMobileView ? 'h3' : 'h2',
22+
])}
23+
>
24+
<FormattedMessage
25+
id="profile.your.certificates"
26+
defaultMessage="Your certificates"
27+
description="heading for the certificates section"
28+
/>
29+
</p>
30+
</div>
31+
<div className="col justify-content-start align-items-start pt-2 p-0">
32+
<p className={classNames([
33+
'font-weight-normal text-gray-800 m-0 p-0',
34+
isMobileView ? 'h5' : 'p',
35+
])}
36+
>
37+
<FormattedMessage
38+
id="profile.certificates.description"
39+
defaultMessage="Your learner records information is only visible to you. Only your username is visible to others on {siteName}."
40+
description="description of the certificates section"
41+
values={{
42+
siteName: getConfig().SITE_NAME,
43+
}}
44+
/>
45+
</p>
46+
</div>
2147
</div>
22-
<div className="col justify-content-start align-items-start pt-2 p-0">
23-
<p className="font-weight-normal text-gray-800 m-0 p-0">
48+
{certificates?.length > 0 ? (
49+
<div className="col">
50+
<div className={classNames(
51+
'row align-items-center pt-5 g-3rem',
52+
{ 'justify-content-center': isTabletView },
53+
)}
54+
>
55+
{certificates.map(certificate => (
56+
<CertificateCard key={certificate.courseId} {...certificate} />
57+
))}
58+
</div>
59+
</div>
60+
) : (
61+
<div className="pt-5">
2462
<FormattedMessage
25-
id="profile.certificates.description"
26-
defaultMessage="Your learner records information is only visible to you. Only your username is visible to others on {siteName}."
27-
description="description of the certificates section"
28-
values={{
29-
siteName: getConfig().SITE_NAME,
30-
}}
63+
id="profile.no.certificates"
64+
defaultMessage="You don't have any certificates yet."
65+
description="displays when user has no course completion certificates"
3166
/>
32-
</p>
33-
</div>
34-
</div>
35-
{certificates?.length > 0 ? (
36-
<div className="col">
37-
<div className="row align-items-center pt-5 g-3rem">
38-
{certificates.map(certificate => (
39-
<CertificateCard key={certificate.courseId} {...certificate} />
40-
))}
4167
</div>
42-
</div>
43-
) : (
44-
<div className="pt-5">
45-
<FormattedMessage
46-
id="profile.no.certificates"
47-
defaultMessage="You don't have any certificates yet."
48-
description="displays when user has no course completion certificates"
49-
/>
50-
</div>
51-
)}
52-
</div>
53-
);
68+
)}
69+
</div>
70+
);
71+
};
5472

5573
Certificates.propTypes = {
5674
certificates: PropTypes.arrayOf(PropTypes.shape({

src/profile-v2/ProfilePage.jsx

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ import { sendTrackingLogEvent } from '@edx/frontend-platform/analytics';
77
import { ensureConfig, getConfig } from '@edx/frontend-platform';
88
import { AppContext } from '@edx/frontend-platform/react';
99
import { useIntl } from '@edx/frontend-platform/i18n';
10-
import { Alert, Hyperlink } from '@openedx/paragon';
10+
import {
11+
Alert,
12+
Hyperlink,
13+
breakpoints,
14+
useWindowSize,
15+
} from '@openedx/paragon';
16+
import classNames from 'classnames';
1117
import {
1218
fetchProfile,
1319
saveProfilePhoto,
@@ -42,6 +48,8 @@ const ProfilePage = ({ params }) => {
4248
} = useSelector(profilePageSelector);
4349

4450
const [viewMyRecordsUrl, setViewMyRecordsUrl] = useState(null);
51+
const isMobileView = useWindowSize().width <= breakpoints.small.minWidth;
52+
const isTabletView = useWindowSize().width <= breakpoints.medium.minWidth;
4553

4654
useEffect(() => {
4755
const { CREDENTIALS_BASE_URL } = context.config;
@@ -81,7 +89,10 @@ const ProfilePage = ({ params }) => {
8189

8290
return (
8391
<Hyperlink
84-
className="btn btn-brand btn-rounded font-weight-normal px-4 py-0625rem text-nowrap"
92+
className={classNames(
93+
'btn btn-brand btn-rounded font-weight-normal px-4 py-0625rem text-nowrap',
94+
{ 'btn-sm': isMobileView },
95+
)}
8596
target="_blank"
8697
showLaunchIcon={false}
8798
destination={viewMyRecordsUrl}
@@ -109,10 +120,21 @@ const ProfilePage = ({ params }) => {
109120
<PageLoading srMessage={intl.formatMessage(messages['profile.loading'])} />
110121
) : (
111122
<>
112-
<div className="profile-page-bg-banner bg-primary d-md-block align-items-center px-75rem py-4rem h-100 w-100">
123+
<div
124+
className={classNames(
125+
'profile-page-bg-banner bg-primary d-md-block align-items-center py-4rem h-100 w-100',
126+
{ 'px-4.5': isMobileView },
127+
{ 'px-75rem': !isMobileView },
128+
)}
129+
>
113130
<div className="col container-fluid w-100 h-100 bg-white py-0 px-25rem rounded-75">
114131
<div className="col h-100 w-100 py-4 px-0 justify-content-start g-15rem">
115-
<div className="row-auto d-flex flex-wrap align-items-center h-100 w-100 justify-content-start g-15rem">
132+
<div
133+
className={classNames([
134+
'row-auto d-flex flex-wrap align-items-center h-100 w-100 justify-content-start g-15rem',
135+
isMobileView || isTabletView ? 'flex-column' : 'flex-row',
136+
])}
137+
>
116138
<ProfileAvatar
117139
className="col p-0"
118140
src={profileImage.src}
@@ -122,17 +144,46 @@ const ProfilePage = ({ params }) => {
122144
savePhotoState={savePhotoState}
123145
isEditable={isAuthenticatedUserProfile() && !requiresParentalConsent}
124146
/>
125-
<div className="col justify-content-start align-items-start h-100 w-100 m-0 p-0">
126-
<h1 className="row h3 m-0 font-weight-bold text-truncate text-primary-500">{params.username}</h1>
147+
<div
148+
className={classNames([
149+
'col h-100 w-100 m-0 p-0',
150+
isMobileView || isTabletView
151+
? 'd-flex flex-column justify-content-center align-items-center'
152+
: 'justify-content-start align-items-start',
153+
])}
154+
>
155+
<p className={classNames([
156+
'row m-0 font-weight-bold text-truncate text-primary-500',
157+
isMobileView ? 'h4' : 'h3',
158+
])}
159+
>
160+
{params.username}
161+
</p>
127162
{isBlockVisible(name) && (
128-
<p className="row pt-2 text-gray-800 font-weight-normal m-0">{name}</p>
163+
<p className={classNames([
164+
'row pt-2 text-gray-800 font-weight-normal m-0',
165+
isMobileView ? 'h5' : 'p',
166+
])}
167+
>
168+
{name}
169+
</p>
170+
)}
171+
<div className={classNames(
172+
'row pt-2 m-0',
173+
isMobileView
174+
? 'd-flex justify-content-center align-items-center flex-column'
175+
: 'g-1rem',
129176
)}
130-
<div className="row pt-2 m-0 g-1rem">
177+
>
131178
<DateJoined date={dateJoined} />
132179
<UserCertificateSummary count={courseCertificates.length} />
133180
</div>
134181
</div>
135-
<div className="col-auto p-0">
182+
<div className={classNames([
183+
'p-0 ',
184+
isMobileView || isTabletView ? 'col d-flex justify-content-center' : 'col-auto',
185+
])}
186+
>
136187
{renderViewMyRecordsButton()}
137188
</div>
138189
</div>
Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
import React from 'react';
22
import { FormattedMessage } from '@edx/frontend-platform/i18n';
33
import { getConfig } from '@edx/frontend-platform';
4+
import classNames from 'classnames';
5+
import { breakpoints, useWindowSize } from '@openedx/paragon';
46

5-
const UsernameDescription = () => (
6-
<p className="text-gray-800 font-weight-normal m-0">
7-
<FormattedMessage
8-
id="profile.username.description"
9-
defaultMessage="Your learner records information is only visible to you. Only your username is visible to others on {siteName}."
10-
description="A description of the username field"
11-
values={{
12-
siteName: getConfig().SITE_NAME,
13-
}}
14-
/>
15-
</p>
16-
);
7+
const UsernameDescription = () => {
8+
const isMobileView = useWindowSize().width <= breakpoints.small.minWidth;
9+
return (
10+
<p className={classNames([
11+
'text-gray-800 font-weight-normal m-0',
12+
isMobileView ? 'h5' : 'p',
13+
])}
14+
>
15+
<FormattedMessage
16+
id="profile.username.description"
17+
defaultMessage="Your learner records information is only visible to you. Only your username is visible to others on {siteName}."
18+
description="A description of the username field"
19+
values={{
20+
siteName: getConfig().SITE_NAME,
21+
}}
22+
/>
23+
</p>
24+
);
25+
};
1726

1827
export default UsernameDescription;

src/profile-v2/index.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@
151151
max-width: 32em;
152152
}
153153

154+
.max-width-19rem{
155+
max-width: 19rem;
156+
}
154157
.width-75rem {
155158
width: 75rem;
156159
}

0 commit comments

Comments
 (0)