Skip to content
This repository has been archived by the owner on Mar 23, 2023. It is now read-only.

Commit

Permalink
refactor: implement new design for the page create profile (#2941)
Browse files Browse the repository at this point in the history
  • Loading branch information
brenopolanski authored Oct 8, 2020
1 parent 4531ad3 commit 4f3f177
Show file tree
Hide file tree
Showing 10 changed files with 543 additions and 1,027 deletions.
2 changes: 1 addition & 1 deletion src/app/assets/svg/upload.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
124 changes: 80 additions & 44 deletions src/app/components/SelectProfileImage/SelectProfileImage.tsx
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Tippy from "@tippyjs/react";
import { Button } from "app/components/Button";
import { Icon } from "app/components/Icon";
import React, { useMemo } from "react";
Expand All @@ -6,23 +7,34 @@ import tw, { styled } from "twin.macro";
import { openFile } from "utils/electron-utils";

type SelectProfileImageProps = {
className?: string;
value?: string;
name?: string;
showLabel?: boolean;
onSelect: (raw: string) => void;
};

const ProfileImageStyled = styled.div`
& {
${tw`relative inline-flex items-center justify-center overflow-hidden rounded`};
${tw`relative inline-flex items-center justify-center overflow-hidden rounded cursor-pointer`};
}
&:after {
content: "";
box-shadow: 0px 0px 0px 100px rgba(0, 0, 0, 0.4);
${tw`absolute w-22 h-22 left-1 top-1 rounded-full`};
box-shadow: 0 0 0 100px rgba(0, 0, 0, 0.4);
${tw`absolute rounded-full w-22 h-22 left-1 top-1`};
}
&:hover .upload-button-overlay {
${tw`block`};
div {
background-color: rgba(0, 0, 0, 0.7);
}
}
`;

export const SelectProfileImage = ({ value, name, onSelect }: SelectProfileImageProps) => {
export const SelectProfileImage = ({ className, value, name, showLabel, onSelect }: SelectProfileImageProps) => {
const { t } = useTranslation();

const handleUploadImage = async () => {
Expand All @@ -39,52 +51,76 @@ export const SelectProfileImage = ({ value, name, onSelect }: SelectProfileImage
const isSvg = useMemo(() => value && value.endsWith("</svg>"), [value]);

return (
<div className="group">
<span className="text-sm font-semibold transition-colors duration-100 group-hover:text-theme-primary text-theme-neutral-dark">
{t("SETTINGS.GENERAL.PERSONAL.PROFILE_IMAGE")}
</span>
<div className={`group ${className}`}>
{showLabel && (
<span className="text-sm font-semibold transition-colors duration-100 group-hover:text-theme-primary text-theme-neutral-dark">
{t("SETTINGS.GENERAL.PERSONAL.PROFILE_IMAGE")}
</span>
)}

<div className="flex flex-row mt-2">
<div className="flex items-center justify-center w-24 h-24 mr-6 border-2 border-dashed rounded border-theme-primary-contrast">
<div className="overflow-hidden rounded-full w-22 h-22">
<Button
className="w-22 h-22"
variant="plain"
onClick={handleUploadImage}
data-testid="SelectProfileImage__upload-button"
>
<Icon name="Upload" />
</Button>
</div>
</div>
{value && (
{!value ? (
<Tippy content={t("SETTINGS.GENERAL.PERSONAL.UPLOAD_AVATAR")}>
<div className="flex items-center justify-center w-24 h-24 border-2 border-dashed rounded border-theme-primary-contrast">
<div className="overflow-hidden rounded-full w-22 h-22">
<Button
className="w-22 h-22"
variant="plain"
onClick={handleUploadImage}
data-testid="SelectProfileImage__upload-button"
>
<Icon name="Upload" className="text-theme-primary" />
</Button>
</div>
</div>
</Tippy>
) : (
<div className="relative w-24 h-24 rounded bg-theme-neutral-contrast">
<ProfileImageStyled>
<img
src={isSvg ? `data:image/svg+xml;utf8,${value}` : value}
className="object-cover w-24 h-24 bg-center bg-no-repeat bg-cover rounded"
alt="Profile avatar"
/>
{isSvg && (
<span className="absolute text-2xl font-semibold text-theme-background">
{name?.slice(0, 2).toUpperCase()}
</span>
)}
</ProfileImageStyled>
<Button
data-testid="SelectProfileImage__remove-button"
size="icon"
color="danger"
variant="plain"
className="absolute flex items-center justify-center w-6 h-6 p-1 -top-3 -right-3"
onClick={() => onSelect("")}
disabled={!!isSvg}
>
<Icon name="Close" width={12} height={12} />
</Button>
<Tippy content={t("SETTINGS.GENERAL.PERSONAL.UPLOAD_AVATAR")}>
<ProfileImageStyled>
<img
src={isSvg ? `data:image/svg+xml;utf8,${value}` : value}
className="object-cover w-24 h-24 bg-center bg-no-repeat bg-cover rounded"
alt="Profile avatar"
/>
{isSvg && (
<span className="absolute text-2xl font-semibold text-theme-background">
{name?.slice(0, 2).toUpperCase()}
</span>
)}

<div
className="absolute z-50 hidden overflow-hidden rounded-full upload-button-overlay w-22 h-22"
onClick={handleUploadImage}
data-testid="SelectProfileImage__upload-button"
>
<div className="flex items-center justify-center w-22 h-22">
<Icon name="Upload" className="text-white" />
</div>
</div>
</ProfileImageStyled>
</Tippy>
{!isSvg && (
<Tippy content={t("SETTINGS.GENERAL.PERSONAL.DELETE_AVATAR")}>
<Button
size="icon"
color="danger"
variant="plain"
className="absolute flex items-center justify-center w-6 h-6 p-1 -top-3 -right-3"
onClick={() => onSelect("")}
data-testid="SelectProfileImage__remove-button"
>
<Icon name="Close" width={12} height={12} />
</Button>
</Tippy>
)}
</div>
)}
</div>
</div>
);
};

SelectProfileImage.defaultProps = {
showLabel: true,
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`SelectProfileImage should render 1`] = `
<div>
<div
class="group"
class="group undefined"
>
<span
class="text-sm font-semibold transition-colors duration-100 group-hover:text-theme-primary text-theme-neutral-dark"
Expand All @@ -14,7 +14,7 @@ exports[`SelectProfileImage should render 1`] = `
class="flex flex-row mt-2"
>
<div
class="flex items-center justify-center w-24 h-24 mr-6 border-2 border-dashed rounded border-theme-primary-contrast"
class="flex items-center justify-center w-24 h-24 border-2 border-dashed rounded border-theme-primary-contrast"
>
<div
class="overflow-hidden rounded-full w-22 h-22"
Expand All @@ -26,7 +26,7 @@ exports[`SelectProfileImage should render 1`] = `
type="button"
>
<div
class="sc-AxirZ iQaTP"
class="sc-AxirZ iQaTP text-theme-primary"
height="1em"
width="1em"
>
Expand Down
10 changes: 3 additions & 7 deletions src/domains/profile/e2e/create-profile-action.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const nameInput = Selector("input[name=name]");
test("should return an error when submit without required fields", async (t) => {
await t.click(Selector("button").withExactText(translations.PROFILE.CREATE_PROFILE));

await t.click(Selector("button").withExactText(translations.COMMON.COMPLETE));
await t.click(Selector("button").withExactText(translations.COMMON.CREATE));
await t.click(Selector("fieldset p").withText("'Name' is required"));
await t.click(Selector("fieldset p").withText("'Currency' is required"));
await t.click(Selector("h1").withExactText(translations.PROFILE.PAGE_CREATE_PROFILE.TITLE));
Expand All @@ -24,12 +24,10 @@ test("should create a profile and navigate to welcome screen", async (t) => {
await t.expect(getLocation()).contains("/profiles/create");

await t.typeText(nameInput, "Anne Doe");
await t.click(Selector("button").withText("CryptoCompare"));
await t.click(Selector("li.select-list-option").withText("CoinGecko"));
await t.click(Selector("button").withText("Select Currency"));
await t.click(Selector("li.select-list-option").withText("ETH"));
await t.click(Selector("input[name=isDarkMode]").parent());
await t.click(Selector("button").withExactText(translations.COMMON.COMPLETE));
await t.click(Selector("button").withExactText(translations.COMMON.CREATE));

await t.wait(1000); // TODO: the profile loading is async so we need to give it a moment

Expand All @@ -46,12 +44,10 @@ test("should create a profile with password and navigate to welcome screen", asy

await t.typeText(nameInput, "Joe Bloggs");
await t.typeText(Selector("input[name=password]"), "password");
await t.click(Selector("button").withText("CryptoCompare"));
await t.click(Selector("li.select-list-option").withText("CoinGecko"));
await t.click(Selector("button").withText("Select Currency"));
await t.click(Selector("li.select-list-option").withText("ETH"));
await t.click(Selector("input[name=isDarkMode]").parent());
await t.click(Selector("button").withExactText(translations.COMMON.COMPLETE));
await t.click(Selector("button").withExactText(translations.COMMON.CREATE));

await t.wait(1000); // TODO: the profile loading is async so we need to give it a moment

Expand Down
1 change: 1 addition & 0 deletions src/domains/profile/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const translations: { [key: string]: any } = {
PAGE_CREATE_PROFILE: {
TITLE: "Create Profile",
DESCRIPTION: "Sign in via MarketSquare or create a new Profile below.",
NEW_PROFILE: "New Profile",
VALIDATION: {
MAXLENGTH_ERROR: "The Name should have less than {{maxLength}} characters",
},
Expand Down
12 changes: 2 additions & 10 deletions src/domains/profile/pages/CreateProfile/CreateProfile.test.tsx
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const baseSettings = {
EXCHANGE_CURRENCY: "BTC",
LEDGER_UPDATE_METHOD: false,
LOCALE: "en-US",
MARKET_PROVIDER: "coincap",
MARKET_PROVIDER: "cryptocompare",
NAME: "test profile",
SCREENSHOT_PROTECTION: true,
THEME: "light",
Expand Down Expand Up @@ -97,8 +97,6 @@ describe("CreateProfile", () => {
fireEvent.input(getAllByTestId("Input")[0], { target: { value: "test profile" } });
fireEvent.click(getAllByTestId("select-list__toggle-button")[0]);
fireEvent.click(getByTestId("select-list__toggle-option-0"));
fireEvent.click(getAllByTestId("select-list__toggle-button")[1]);
fireEvent.click(getByTestId("select-list__toggle-option-0"));

await act(async () => {
fireEvent.click(getByTestId("CreateProfile__submit-button"));
Expand Down Expand Up @@ -135,7 +133,7 @@ describe("CreateProfile", () => {
});

it("should store profile with password", async () => {
const { asFragment, container, getAllByTestId, getByTestId } = renderWithRouter(
const { asFragment, getAllByTestId, getByTestId } = renderWithRouter(
<EnvironmentProvider env={env}>
<CreateProfile />
</EnvironmentProvider>,
Expand All @@ -149,8 +147,6 @@ describe("CreateProfile", () => {
fireEvent.input(getAllByTestId("Input")[1], { target: { value: "test password" } });
fireEvent.click(getAllByTestId("select-list__toggle-button")[0]);
fireEvent.click(getByTestId("select-list__toggle-option-0"));
fireEvent.click(getAllByTestId("select-list__toggle-button")[1]);
fireEvent.click(getByTestId("select-list__toggle-option-0"));

await act(async () => {
fireEvent.click(getByTestId("CreateProfile__submit-button"));
Expand Down Expand Up @@ -186,8 +182,6 @@ describe("CreateProfile", () => {
fireEvent.input(getAllByTestId("Input")[0], { target: { value: "test profile" } });
fireEvent.click(getAllByTestId("select-list__toggle-button")[0]);
fireEvent.click(getByTestId("select-list__toggle-option-0"));
fireEvent.click(getAllByTestId("select-list__toggle-button")[1]);
fireEvent.click(getByTestId("select-list__toggle-option-0"));

await act(async () => {
fireEvent.click(getByTestId("CreateProfile__submit-button"));
Expand Down Expand Up @@ -226,8 +220,6 @@ describe("CreateProfile", () => {
fireEvent.input(getAllByTestId("Input")[0], { target: { value: "test profile" } });
fireEvent.click(getAllByTestId("select-list__toggle-button")[0]);
fireEvent.click(getByTestId("select-list__toggle-option-0"));
fireEvent.click(getAllByTestId("select-list__toggle-button")[1]);
fireEvent.click(getByTestId("select-list__toggle-option-0"));

await act(async () => {
fireEvent.click(getByTestId("CreateProfile__submit-button"));
Expand Down
Loading

0 comments on commit 4f3f177

Please sign in to comment.