Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fixed responsiveness issues on mobile view #1133

Open
wants to merge 3 commits into
base: 2u-main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 42 additions & 7 deletions src/profile-v2/CertificateCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { FormattedDate, FormattedMessage, useIntl } from '@edx/frontend-platform
import { Hyperlink } from '@openedx/paragon';
import get from 'lodash.get';

import classNames from 'classnames';
import professionalCertificateSVG from './assets/professional-certificate.svg';
import verifiedCertificateSVG from './assets/verified-certificate.svg';
import messages from './Certificates.messages';
import { useIsOnMobileScreen } from './data/hooks';

const CertificateCard = ({
certificateType,
Expand All @@ -27,6 +29,8 @@ const CertificateCard = ({
audit: null,
}[certificateType] || null;

const isMobileView = useIsOnMobileScreen();

return (
<div
key={`${modifiedDate}-${courseId}`}
Expand All @@ -37,24 +41,47 @@ const CertificateCard = ({
className="certificate-type-illustration"
style={{ backgroundImage: `url(${certificateIllustration})` }}
/>
<div className="d-flex flex-column position-relative p-0 width-19625rem">
<div className={classNames(
'd-flex flex-column position-relative p-0',
{ 'max-width-19rem': isMobileView },
{ 'width-19625rem': !isMobileView },
)}
>
<div className="w-100 color-black">
<p className="small mb-0 font-weight-normal">
<p className={classNames([
'mb-0 font-weight-normal',
isMobileView ? 'x-small' : 'small',
])}
>
eemaanamir marked this conversation as resolved.
Show resolved Hide resolved
{intl.formatMessage(get(
messages,
`profile.certificates.types.${certificateType}`,
messages['profile.certificates.types.unknown'],
))}
</p>
<h4 className="m-0 color-black">{courseDisplayName}</h4>
<p className="small mb-0">
<p className={classNames([
'm-0 color-black',
isMobileView ? 'h5' : 'h4',
])}
>
Comment on lines +62 to +66
Copy link
Contributor

@sundasnoreen12 sundasnoreen12 Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use this <p className={classNames('m-0 color-black', {
'h5': isMobileView,
'h4': !isMobileView,
})}>

{courseDisplayName}
</p>
<p className={classNames([
'mb-0',
isMobileView ? 'x-small' : 'small',
])}
>
eemaanamir marked this conversation as resolved.
Show resolved Hide resolved
<FormattedMessage
id="profile.certificate.organization.label"
defaultMessage="From"
/>
</p>
<h5 className="mb-0 color-black">{courseOrganization}</h5>
<p className="small mb-0">
<p className={classNames([
'mb-0',
isMobileView ? 'x-small' : 'small',
])}
>
Comment on lines +80 to +84
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

<FormattedMessage
id="profile.certificate.completion.date.label"
defaultMessage="Completed on {date}"
Expand All @@ -69,12 +96,20 @@ const CertificateCard = ({
destination={downloadUrl}
target="_blank"
showLaunchIcon={false}
className="btn btn-primary btn-rounded font-weight-normal px-4 py-0625rem"
className={classNames(
'btn btn-primary btn-rounded font-weight-normal px-4 py-0625rem',
{ 'btn-sm': isMobileView },
)}
>
{intl.formatMessage(messages['profile.certificates.view.certificate'])}
</Hyperlink>
</div>
<p className="small mb-0 pt-3">
<p
className={classNames([
'mb-0 pt-3',
isMobileView ? 'x-small' : 'small',
])}
>
<FormattedMessage
id="profile.certificate.uuid"
defaultMessage="Credential ID {certificate_uuid}"
Expand Down
107 changes: 67 additions & 40 deletions src/profile-v2/Certificates.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,80 @@ import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { connect } from 'react-redux';
import { getConfig } from '@edx/frontend-platform';

import classNames from 'classnames';
import CertificateCard from './CertificateCard';
import { certificatesSelector } from './data/selectors';
import { useIsOnMobileScreen, useIsOnTabletScreen } from './data/hooks';

const Certificates = ({ certificates }) => (
<div>
<div className="col justify-content-start align-items-start g-5rem p-0">
<div className="col align-self-stretch height-2625rem justify-content-start align-items-start p-0">
<h2 className="font-weight-bold text-primary-500 m-0">
<FormattedMessage
id="profile.your.certificates"
defaultMessage="Your certificates"
description="heading for the certificates section"
/>
</h2>
const Certificates = ({ certificates }) => {
const isMobileView = useIsOnMobileScreen();
const isTabletView = useIsOnTabletScreen();
return (
<div>
<div className="col justify-content-start align-items-start g-5rem p-0">
<div className="col align-self-stretch height-2625rem justify-content-start align-items-start p-0">
<p className={classNames([
'font-weight-bold text-primary-500 m-0',
isMobileView ? 'h3' : 'h2',
])}
Comment on lines +19 to +22
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow above pattern for classNames and change wherever used

>
<FormattedMessage
id="profile.your.certificates"
defaultMessage="Your certificates"
description="heading for the certificates section"
/>
</p>
</div>
<div className="col justify-content-start align-items-start pt-2 p-0">
<p className={classNames([
'font-weight-normal text-gray-800 m-0 p-0',
isMobileView ? 'h5' : 'p',
])}
>
<FormattedMessage
id="profile.certificates.description"
defaultMessage="Your learner records information is only visible to you. Only your username is visible to others on {siteName}."
description="description of the certificates section"
values={{
siteName: getConfig().SITE_NAME,
}}
/>
</p>
</div>
</div>
<div className="col justify-content-start align-items-start pt-2 p-0">
<p className="font-weight-normal text-gray-800 m-0 p-0">
{certificates?.length > 0 ? (
<div className="col">
<div className={classNames(
'row align-items-center pt-5 g-3rem',
{ 'justify-content-center': isTabletView },
)}
>
{certificates.map(certificate => (
<CertificateCard
key={certificate.courseId}
certificateType={certificate.certificateType}
courseDisplayName={certificate.courseDisplayName}
courseOrganization={certificate.courseOrganization}
modifiedDate={certificate.modifiedDate}
downloadUrl={certificate.downloadUrl}
courseId={certificate.courseId}
uuid={certificate.uuid}
/>
))}
</div>
</div>
) : (
<div className="pt-5">
<FormattedMessage
id="profile.certificates.description"
defaultMessage="Your learner records information is only visible to you. Only your username is visible to others on {siteName}."
description="description of the certificates section"
values={{
siteName: getConfig().SITE_NAME,
}}
id="profile.no.certificates"
defaultMessage="You don't have any certificates yet."
description="displays when user has no course completion certificates"
/>
</p>
</div>
</div>
{certificates?.length > 0 ? (
<div className="col">
<div className="row align-items-center pt-5 g-3rem">
{certificates.map(certificate => (
<CertificateCard key={certificate.courseId} {...certificate} />
))}
</div>
</div>
) : (
<div className="pt-5">
<FormattedMessage
id="profile.no.certificates"
defaultMessage="You don't have any certificates yet."
description="displays when user has no course completion certificates"
/>
</div>
)}
</div>
);
)}
</div>
);
};

Certificates.propTypes = {
certificates: PropTypes.arrayOf(PropTypes.shape({
Expand Down
63 changes: 55 additions & 8 deletions src/profile-v2/ProfilePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { AppContext } from '@edx/frontend-platform/react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Alert, Hyperlink } from '@openedx/paragon';
import classNames from 'classnames';
import {
fetchProfile,
saveProfilePhoto,
Expand All @@ -22,6 +23,7 @@
import { profilePageSelector } from './data/selectors';
import messages from './ProfilePage.messages';
import withParams from '../utils/hoc';
import { useIsOnMobileScreen, useIsOnTabletScreen } from './data/hooks';

ensureConfig(['CREDENTIALS_BASE_URL', 'LMS_BASE_URL'], 'ProfilePage');

Expand All @@ -42,6 +44,8 @@
} = useSelector(profilePageSelector);

const [viewMyRecordsUrl, setViewMyRecordsUrl] = useState(null);
const isMobileView = useIsOnMobileScreen();
const isTabletView = useIsOnTabletScreen();

useEffect(() => {
const { CREDENTIALS_BASE_URL } = context.config;
Expand Down Expand Up @@ -81,7 +85,10 @@

return (
<Hyperlink
className="btn btn-brand btn-rounded font-weight-normal px-4 py-0625rem text-nowrap"
className={classNames(
'btn btn-brand btn-rounded font-weight-normal px-4 py-0625rem text-nowrap',
{ 'btn-sm': isMobileView },
)}
target="_blank"
showLaunchIcon={false}
destination={viewMyRecordsUrl}
Expand Down Expand Up @@ -109,10 +116,21 @@
<PageLoading srMessage={intl.formatMessage(messages['profile.loading'])} />
) : (
<>
<div className="profile-page-bg-banner bg-primary d-md-block align-items-center px-75rem py-4rem h-100 w-100">
<div
className={classNames(
'profile-page-bg-banner bg-primary d-md-block align-items-center py-4rem h-100 w-100',
{ 'px-4.5': isMobileView },
{ 'px-75rem': !isMobileView },
)}
>
<div className="col container-fluid w-100 h-100 bg-white py-0 px-25rem rounded-75">
<div className="col h-100 w-100 py-4 px-0 justify-content-start g-15rem">
<div className="row-auto d-flex flex-wrap align-items-center h-100 w-100 justify-content-start g-15rem">
<div
className={classNames([
'row-auto d-flex flex-wrap align-items-center h-100 w-100 justify-content-start g-15rem',
isMobileView || isTabletView ? 'flex-column' : 'flex-row',
])}
>
<ProfileAvatar
className="col p-0"
src={profileImage.src}
Expand All @@ -122,17 +140,46 @@
savePhotoState={savePhotoState}
isEditable={isAuthenticatedUserProfile() && !requiresParentalConsent}
/>
<div className="col justify-content-start align-items-start h-100 w-100 m-0 p-0">
<h1 className="row h3 m-0 font-weight-bold text-truncate text-primary-500">{params.username}</h1>
<div
className={classNames([
'col h-100 w-100 m-0 p-0',
isMobileView || isTabletView
? 'd-flex flex-column justify-content-center align-items-center'

Check warning on line 147 in src/profile-v2/ProfilePage.jsx

View check run for this annotation

Codecov / codecov/patch

src/profile-v2/ProfilePage.jsx#L147

Added line #L147 was not covered by tests
: 'justify-content-start align-items-start',
])}
>
<p className={classNames([
'row m-0 font-weight-bold text-truncate text-primary-500',
isMobileView ? 'h4' : 'h3',
])}
>
{params.username}
</p>
{isBlockVisible(name) && (
<p className="row pt-2 text-gray-800 font-weight-normal m-0">{name}</p>
<p className={classNames([
'row pt-2 text-gray-800 font-weight-normal m-0',
isMobileView ? 'h5' : 'p',
])}
>
{name}
</p>
)}
<div className={classNames(
'row pt-2 m-0',
isMobileView
? 'd-flex justify-content-center align-items-center flex-column'

Check warning on line 170 in src/profile-v2/ProfilePage.jsx

View check run for this annotation

Codecov / codecov/patch

src/profile-v2/ProfilePage.jsx#L170

Added line #L170 was not covered by tests
: 'g-1rem',
)}
<div className="row pt-2 m-0 g-1rem">
>
<DateJoined date={dateJoined} />
<UserCertificateSummary count={courseCertificates.length} />
</div>
</div>
<div className="col-auto p-0">
<div className={classNames([
'p-0 ',
isMobileView || isTabletView ? 'col d-flex justify-content-center' : 'col-auto',
])}
>
{renderViewMyRecordsButton()}
</div>
</div>
Expand Down
33 changes: 21 additions & 12 deletions src/profile-v2/UsernameDescription.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import React from 'react';
import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import classNames from 'classnames';
import { useIsOnMobileScreen } from './data/hooks';

const UsernameDescription = () => (
<p className="text-gray-800 font-weight-normal m-0">
<FormattedMessage
id="profile.username.description"
defaultMessage="Your learner records information is only visible to you. Only your username is visible to others on {siteName}."
description="A description of the username field"
values={{
siteName: getConfig().SITE_NAME,
}}
/>
</p>
);
const UsernameDescription = () => {
const isMobileView = useIsOnMobileScreen();
return (
<p className={classNames([
'text-gray-800 font-weight-normal m-0',
isMobileView ? 'h5' : 'p',
])}
>
<FormattedMessage
id="profile.username.description"
defaultMessage="Your learner records information is only visible to you. Only your username is visible to others on {siteName}."
description="A description of the username field"
values={{
siteName: getConfig().SITE_NAME,
}}
/>
</p>
);
};

export default UsernameDescription;
Loading