feat(dashboard-v2): proper copies on user settings pages + fix for account removal redirection

This commit is contained in:
Michał Leszczyk 2022-04-12 13:22:26 +02:00
parent 38407f6a31
commit b572cdf72c
No known key found for this signature in database
GPG Key ID: FA123CA8BAA2FBF4
8 changed files with 63 additions and 29 deletions

View File

@ -1,7 +1,7 @@
import { useEffect, useState } from "react";
import { useUser } from "../../contexts/user";
import { SimpleUploadIcon } from "../Icons";
// import { SimpleUploadIcon } from "../Icons";
const AVATAR_PLACEHOLDER = "/images/avatar-placeholder.svg";
@ -20,6 +20,7 @@ export const AvatarUploader = (props) => {
>
<img src={imageUrl} className="w-[160px]" alt="" />
</div>
{/* TODO: uncomment when avatar uploads work
<div className="flex justify-center">
<button
className="flex items-center gap-4 hover:underline decoration-1 decoration-dashed underline-offset-2 decoration-gray-400"
@ -28,8 +29,8 @@ export const AvatarUploader = (props) => {
>
<SimpleUploadIcon size={20} className="shrink-0" /> Upload profile picture
</button>
{/* TODO: actual uploading */}
</div>
*/}
</div>
);
};

View File

@ -1,5 +1,6 @@
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import prettyBytes from "pretty-bytes";
import { useUser } from "../../contexts/user";
import useActivePlan from "../../hooks/useActivePlan";
@ -28,17 +29,20 @@ const CurrentPlan = () => {
}
return (
<div>
<div className="flex flex-col h-full">
<h4>{activePlan.name}</h4>
<div className="text-palette-400">
{activePlan.price === 0 && <p>100GB without paying a dime! 🎉</p>}
<div className="text-palette-400 justify-between flex flex-col grow">
{activePlan.price === 0 && activePlan.limits && (
<p>{prettyBytes(activePlan.limits.storageLimit)} without paying a dime! 🎉</p>
)}
{activePlan.price !== 0 &&
(user.subscriptionCancelAtPeriodEnd ? (
<p>Your subscription expires {dayjs(user.subscribedUntil).fromNow()}</p>
) : (
<p className="first-letter:uppercase">{dayjs(user.subscribedUntil).fromNow(true)} until the next payment</p>
))}
<LatestPayment user={user} />
{user.subscriptionStatus && <LatestPayment user={user} />}
<SuggestedPlan plans={plans} activePlan={activePlan} />
</div>
</div>

View File

@ -1,8 +1,19 @@
import * as React from "react";
import styled from "styled-components";
import { PageContainer } from "../PageContainer";
const FooterLink = styled.a.attrs({
className: "text-palette-400 underline decoration-dotted decoration-offset-4 decoration-1",
rel: "noreferrer",
target: "_blank",
})``;
export const Footer = () => (
<PageContainer className="font-content text-palette-300 py-4">
<p>© Skynet Labs Inc. All rights reserved.</p>
<p>
Made by <FooterLink href="https://skynetlabs.com">Skynet Labs</FooterLink>. Open-sourced{" "}
<FooterLink href="https://github.com/SkynetLabs/skynet-webportal">on Github</FooterLink>.
</p>
</PageContainer>
);

View File

@ -118,7 +118,7 @@ const Uploader = ({ mode }) => {
</div>
{uploads.length > 0 && (
<div className="flex flex-col space-y-4 py-10">
<div className="flex flex-col space-y-4 pt-6 pb-10">
{uploads.map((upload) => (
<UploaderItem key={upload.id} onUploadStateChange={onUploadStateChange} upload={upload} />
))}

View File

@ -34,8 +34,9 @@ export const AccountRemovalForm = ({ abort, onSuccess }) => {
<Form className="flex flex-col gap-4">
<div>
<h4>Delete account</h4>
<p>This will completely delete your account.</p>
<p>
This will completely delete your account. <strong>This process can't be undone.</strong>
<strong>This process cannot be undone.</strong>
</p>
</div>

View File

@ -38,8 +38,8 @@ const ExportPage = () => {
<section>
<h4>Export</h4>
<p>
Et quidem exercitus quid ex eo delectu rerum, quem modo ista sis aequitate. Probabo, inquit, modo dixi,
constituto.
Select the items you want to export. You can use this data to migrate your account to another Skynet
portal.
</p>
</section>
<hr />

View File

@ -8,6 +8,10 @@ import { Modal } from "../../components/Modal/Modal";
import { AccountRemovalForm } from "../../components/forms/AccountRemovalForm";
import { Alert } from "../../components/Alert";
import { Metadata } from "../../components/Metadata";
import HighlightedLink from "../../components/HighlightedLink";
import { AvatarUploader } from "../../components/AvatarUploader/AvatarUploader";
import { useMedia } from "react-use";
import theme from "../../lib/theme";
const State = {
Pure: "PURE",
@ -19,10 +23,16 @@ const AccountPage = () => {
const { user, mutate: reloadUser } = useUser();
const [state, setState] = useState(State.Pure);
const [removalInitiated, setRemovalInitiated] = useState(false);
const isLargeScreen = useMedia(`(min-width: ${theme.screens.xl})`);
const prompt = () => setRemovalInitiated(true);
const abort = () => setRemovalInitiated(false);
const onAccountRemoved = useCallback(async () => {
await reloadUser(null);
await navigate("/auth/login");
}, [reloadUser]);
const onSettingsUpdated = useCallback(
async (updatedState) => {
try {
@ -45,14 +55,7 @@ const AccountPage = () => {
</Metadata>
<div className="flex flex-col xl:flex-row">
<div className="flex flex-col gap-10 lg:shrink-0 lg:max-w-[576px] xl:max-w-[524px]">
<section>
<h4>Account</h4>
<p>
Tum dicere exorsus est laborum et quasi involuta aperiri, altera prompta et expedita. Primum igitur,
inquit, modo ista sis aequitate.
</p>
</section>
<hr />
<section className="flex flex-col gap-8">
{state === State.Failure && (
<Alert $variant="error">There was an error processing your request. Please try again later.</Alert>
@ -63,7 +66,23 @@ const AccountPage = () => {
<hr />
<section>
<h6 className="text-palette-400">Delete account</h6>
<p>This will completely delete your account. This process can't be undone.</p>
<div className="my-4">
<p>
This action will delete your account and <strong>cannot be undone</strong>.
</p>
<p>
Your uploaded files will remain accessible while any portal continues to{" "}
<HighlightedLink
as="a"
href="https://support.skynetlabs.com/key-concepts/faqs#what-is-pinning"
target="_blank"
rel="noreferrer"
>
pin
</HighlightedLink>{" "}
them to Skynet.
</p>
</div>
<button
type="button"
onClick={prompt}
@ -73,9 +92,12 @@ const AccountPage = () => {
</button>
</section>
</div>
<div className="flex w-full justify-start xl:justify-end">
{isLargeScreen && <AvatarUploader className="flex flex-col gap-4" />}
</div>
{removalInitiated && (
<Modal onClose={abort} className="text-center">
<AccountRemovalForm abort={abort} onSuccess={() => navigate("/auth/login")} />
<AccountRemovalForm abort={abort} onSuccess={onAccountRemoved} />
</Modal>
)}
</div>

View File

@ -18,18 +18,13 @@ const NotificationsPage = () => {
<section>
{/* TODO: saves on change */}
<Switch onChange={console.info.bind(console)} labelClassName="!items-start flex-col md:flex-row">
I agreee to get the latest news, updates and special offers delivered to my email inbox.
I agree to receive emails of the latest news, updates and offers.
</Switch>
</section>
<hr />
<section>
<h6 className="text-palette-300">Statistics</h6>
{/* TODO: proper content :) */}
<p>
Si sine causa, nollem me tamen laudandis maioribus meis corrupisti nec in malis. Si sine causa, mox
videro.
</p>
<p>Check below to be notified by email when your usage approaches your plan's limits.</p>
<ul className="mt-7 flex flex-col gap-2">
<li>
{/* TODO: saves on change */}
@ -37,7 +32,7 @@ const NotificationsPage = () => {
</li>
<li>
{/* TODO: saves on change */}
<Switch onChange={console.info.bind(console)}>File limit</Switch>
<Switch onChange={console.info.bind(console)}>Files limit</Switch>
</li>
</ul>
</section>