keypad and settings pages
This commit is contained in:
58
app/settings/pages/settings.tsx
Normal file
58
app/settings/pages/settings.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import type { BlitzPage } from "blitz";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCreditCard, faUserCircle } from "@fortawesome/pro-regular-svg-icons";
|
||||
|
||||
import Layout from "../../core/layouts/layout";
|
||||
|
||||
import appLogger from "../../../integrations/logger";
|
||||
import useRequireOnboarding from "../../core/hooks/use-require-onboarding";
|
||||
|
||||
const logger = appLogger.child({ page: "/settings" });
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
const navigation = [
|
||||
{
|
||||
name: "Account",
|
||||
href: "/settings/account",
|
||||
icon: ({ className = "w-8 h-8" }) => (
|
||||
<FontAwesomeIcon size="lg" className={className} icon={faUserCircle} />
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Billing",
|
||||
href: "/settings/billing",
|
||||
icon: ({ className = "w-8 h-8" }) => (
|
||||
<FontAwesomeIcon size="lg" className={className} icon={faCreditCard} />
|
||||
),
|
||||
},
|
||||
];
|
||||
/* eslint-enable react/display-name */
|
||||
|
||||
const Settings: BlitzPage = () => {
|
||||
useRequireOnboarding();
|
||||
|
||||
return (
|
||||
<Layout title="Settings">
|
||||
<div className="flex flex-col space-y-6 p-6">
|
||||
<aside className="py-6 lg:col-span-3">
|
||||
<nav className="space-y-1">
|
||||
{navigation.map((item) => (
|
||||
<a
|
||||
key={item.name}
|
||||
href={item.href}
|
||||
className="border-transparent text-gray-900 hover:bg-gray-50 hover:text-gray-900 group border-l-4 px-3 py-2 flex items-center text-sm font-medium"
|
||||
>
|
||||
<item.icon className="text-gray-400 group-hover:text-gray-500 flex-shrink-0 -ml-1 mr-3 h-6 w-6" />
|
||||
<span className="truncate">{item.name}</span>
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
</aside>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
Settings.authenticate = true;
|
||||
|
||||
export default Settings;
|
36
app/settings/pages/settings/account.tsx
Normal file
36
app/settings/pages/settings/account.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import type { BlitzPage } from "blitz";
|
||||
|
||||
import SettingsLayout from "../../components/settings-layout";
|
||||
import ProfileInformations from "../../components/profile-informations";
|
||||
import Divider from "../../components/divider";
|
||||
import UpdatePassword from "../../components/update-password";
|
||||
import DangerZone from "../../components/danger-zone";
|
||||
import useRequireOnboarding from "../../../core/hooks/use-require-onboarding";
|
||||
|
||||
const Account: BlitzPage = () => {
|
||||
useRequireOnboarding();
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<div className="flex flex-col space-y-6 p-6">
|
||||
<ProfileInformations />
|
||||
|
||||
<div className="hidden lg:block">
|
||||
<Divider />
|
||||
</div>
|
||||
|
||||
<UpdatePassword />
|
||||
|
||||
<div className="hidden lg:block">
|
||||
<Divider />
|
||||
</div>
|
||||
|
||||
<DangerZone />
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
);
|
||||
};
|
||||
|
||||
Account.authenticate = true;
|
||||
|
||||
export default Account;
|
132
app/settings/pages/settings/billing.tsx
Normal file
132
app/settings/pages/settings/billing.tsx
Normal file
@ -0,0 +1,132 @@
|
||||
/* TODO
|
||||
import type { FunctionComponent, MouseEventHandler } from "react";
|
||||
import type { BlitzPage } from "blitz";
|
||||
import { ExternalLinkIcon } from "@heroicons/react/outline";
|
||||
|
||||
import SettingsLayout from "../../components/settings/settings-layout";
|
||||
import SettingsSection from "../../components/settings/settings-section";
|
||||
import BillingPlans from "../../components/billing/billing-plans";
|
||||
import Divider from "../../components/divider";
|
||||
|
||||
import useSubscription from "../../hooks/use-subscription";
|
||||
|
||||
import { withPageOnboardingRequired } from "../../../lib/session-helpers";
|
||||
import type { Subscription } from "../../database/subscriptions";
|
||||
import { findUserSubscription } from "../../database/subscriptions";
|
||||
|
||||
import appLogger from "../../../lib/logger";
|
||||
import ConnectedLayout from "../../components/connected-layout";
|
||||
|
||||
const logger = appLogger.child({ page: "/account/settings/billing" });
|
||||
|
||||
type Props = {
|
||||
subscription: Subscription | null;
|
||||
};
|
||||
|
||||
const Billing: BlitzPage<Props> = ({ subscription }) => {
|
||||
/!*
|
||||
TODO: I want to be able to
|
||||
- renew subscription (after pause/cancel for example) (message like "your subscription expired, would you like to renew ?")
|
||||
- know when is the last time I paid and for how much
|
||||
- know when is the next time I will pay and for how much
|
||||
*!/
|
||||
const { cancelSubscription, updatePaymentMethod } = useSubscription();
|
||||
|
||||
return (
|
||||
<ConnectedLayout>
|
||||
<SettingsLayout>
|
||||
<div className="flex flex-col space-y-6 p-6">
|
||||
{subscription ? (
|
||||
<>
|
||||
<SettingsSection title="Payment method">
|
||||
<PaddleLink
|
||||
onClick={() =>
|
||||
updatePaymentMethod({
|
||||
updateUrl: subscription.updateUrl,
|
||||
})
|
||||
}
|
||||
text="Update payment method on Paddle"
|
||||
/>
|
||||
</SettingsSection>
|
||||
|
||||
<div className="hidden lg:block">
|
||||
<Divider />
|
||||
</div>
|
||||
|
||||
<SettingsSection title="Plan">
|
||||
<BillingPlans activePlanId={subscription?.planId} />
|
||||
</SettingsSection>
|
||||
|
||||
<div className="hidden lg:block">
|
||||
<Divider />
|
||||
</div>
|
||||
|
||||
<SettingsSection title="Cancel subscription">
|
||||
<PaddleLink
|
||||
onClick={() =>
|
||||
cancelSubscription({
|
||||
cancelUrl: subscription.cancelUrl,
|
||||
})
|
||||
}
|
||||
text="Cancel subscription on Paddle"
|
||||
/>
|
||||
</SettingsSection>
|
||||
</>
|
||||
) : (
|
||||
<SettingsSection title="Plan">
|
||||
<BillingPlans />
|
||||
</SettingsSection>
|
||||
)}
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
</ConnectedLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Billing;
|
||||
|
||||
type PaddleLinkProps = {
|
||||
onClick: MouseEventHandler<HTMLButtonElement>;
|
||||
text: string;
|
||||
};
|
||||
|
||||
const PaddleLink: FunctionComponent<PaddleLinkProps> = ({ onClick, text }) => (
|
||||
<button className="flex space-x-2 items-center text-left" onClick={onClick}>
|
||||
<ExternalLinkIcon className="w-6 h-6 flex-shrink-0" />
|
||||
<span className="transition-colors duration-150 border-b border-transparent hover:border-primary-500">
|
||||
{text}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
|
||||
export const getServerSideProps = withPageOnboardingRequired<Props>(
|
||||
async (context, user) => {
|
||||
// const subscription = await findUserSubscription({ userId: user.id });
|
||||
|
||||
return {
|
||||
props: { subscription: null },
|
||||
};
|
||||
},
|
||||
);
|
||||
*/
|
||||
|
||||
import type { BlitzPage } from "blitz";
|
||||
import { useRouter } from "blitz";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import useRequireOnboarding from "../../../core/hooks/use-require-onboarding";
|
||||
|
||||
const Billing: BlitzPage = () => {
|
||||
useRequireOnboarding();
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
router.push("/messages");
|
||||
});
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
Billing.authenticate = true;
|
||||
|
||||
export default Billing;
|
Reference in New Issue
Block a user