bug fixes
This commit is contained in:
parent
fa1f9873d5
commit
508844dd9d
|
@ -6,6 +6,8 @@ import { signOut } from "next-auth/react";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { useUser } from "@/hooks/store/user";
|
import { useUser } from "@/hooks/store/user";
|
||||||
|
|
||||||
|
const stripeEnabled = process.env.NEXT_PUBLIC_STRIPE === "true";
|
||||||
|
|
||||||
export default function ProfileDropdown() {
|
export default function ProfileDropdown() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { settings, updateSettings } = useLocalSettingsStore();
|
const { settings, updateSettings } = useLocalSettingsStore();
|
||||||
|
@ -73,7 +75,7 @@ export default function ProfileDropdown() {
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{!user.parentSubscriptionId && (
|
{!user.parentSubscriptionId && stripeEnabled && (
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<Link
|
||||||
href="/settings/billing"
|
href="/settings/billing"
|
||||||
|
|
|
@ -2,11 +2,14 @@ import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
|
import { useUser } from "@/hooks/store/user";
|
||||||
|
|
||||||
export default function SettingsSidebar({ className }: { className?: string }) {
|
export default function SettingsSidebar({ className }: { className?: string }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const LINKWARDEN_VERSION = process.env.version;
|
const LINKWARDEN_VERSION = process.env.version;
|
||||||
|
|
||||||
|
const { data: user } = useUser();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [active, setActive] = useState("");
|
const [active, setActive] = useState("");
|
||||||
|
|
||||||
|
@ -73,7 +76,7 @@ export default function SettingsSidebar({ className }: { className?: string }) {
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{process.env.NEXT_PUBLIC_STRIPE && (
|
{process.env.NEXT_PUBLIC_STRIPE && !user.parentSubscriptionId && (
|
||||||
<Link href="/settings/billing">
|
<Link href="/settings/billing">
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
|
|
|
@ -15,7 +15,16 @@ export default async function deleteUserById(
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
where: { id: userId },
|
where: { id: userId },
|
||||||
include: {
|
include: {
|
||||||
subscriptions: true,
|
subscriptions: {
|
||||||
|
include: {
|
||||||
|
user: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
parentSubscription: {
|
||||||
|
include: {
|
||||||
|
user: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -178,24 +187,36 @@ export default async function deleteUserById(
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const listByEmail = await stripe.customers.list({
|
if (user.subscriptions?.id) {
|
||||||
email: user.email?.toLowerCase(),
|
const listByEmail = await stripe.customers.list({
|
||||||
expand: ["data.subscriptions"],
|
email: user.email?.toLowerCase(),
|
||||||
});
|
expand: ["data.subscriptions"],
|
||||||
|
});
|
||||||
|
|
||||||
if (listByEmail.data[0].subscriptions?.data[0].id) {
|
if (listByEmail.data[0].subscriptions?.data[0].id) {
|
||||||
const deleted = await stripe.subscriptions.cancel(
|
const deleted = await stripe.subscriptions.cancel(
|
||||||
listByEmail.data[0].subscriptions?.data[0].id,
|
listByEmail.data[0].subscriptions?.data[0].id,
|
||||||
{
|
{
|
||||||
cancellation_details: {
|
cancellation_details: {
|
||||||
comment: body.cancellation_details?.comment,
|
comment: body.cancellation_details?.comment,
|
||||||
feedback: body.cancellation_details?.feedback,
|
feedback: body.cancellation_details?.feedback,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
response: deleted,
|
||||||
|
status: 200,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else if (user.parentSubscription?.id) {
|
||||||
|
await updateSeats(
|
||||||
|
user.parentSubscription.stripeSubscriptionId,
|
||||||
|
user.parentSubscription.quantity - 1
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
response: deleted,
|
response: "User account and all related data deleted successfully.",
|
||||||
status: 200,
|
status: 200,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,15 @@ export const hasPassedLimit = async (
|
||||||
numberOfImports: number
|
numberOfImports: number
|
||||||
) => {
|
) => {
|
||||||
if (!stripeEnabled) {
|
if (!stripeEnabled) {
|
||||||
return false;
|
const totalLinks = await prisma.link.count({
|
||||||
|
where: {
|
||||||
|
createdBy: {
|
||||||
|
id: userId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return MAX_LINKS_PER_USER - (numberOfImports + totalLinks) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
|
|
|
@ -28,12 +28,13 @@ export default function Billing() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!process.env.NEXT_PUBLIC_STRIPE) router.push("/settings/profile");
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const { data: users = [] } = useUsers();
|
|
||||||
const { data: account } = useUser();
|
const { data: account } = useUser();
|
||||||
|
const { data: users = [] } = useUsers();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!process.env.NEXT_PUBLIC_STRIPE || account.parentSubscriptionId)
|
||||||
|
router.push("/settings/account");
|
||||||
|
}, []);
|
||||||
|
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
const [filteredUsers, setFilteredUsers] = useState<User[]>();
|
const [filteredUsers, setFilteredUsers] = useState<User[]>();
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Link from "next/link";
|
||||||
import Button from "@/components/ui/Button";
|
import Button from "@/components/ui/Button";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import getServerSideProps from "@/lib/client/getServerSideProps";
|
import getServerSideProps from "@/lib/client/getServerSideProps";
|
||||||
|
import { useUser } from "@/hooks/store/user";
|
||||||
|
|
||||||
export default function Delete() {
|
export default function Delete() {
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
|
@ -15,6 +16,7 @@ export default function Delete() {
|
||||||
const [submitLoader, setSubmitLoader] = useState(false);
|
const [submitLoader, setSubmitLoader] = useState(false);
|
||||||
const { data } = useSession();
|
const { data } = useSession();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { data: user } = useUser();
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
const body = {
|
const body = {
|
||||||
|
@ -83,7 +85,7 @@ export default function Delete() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{process.env.NEXT_PUBLIC_STRIPE && (
|
{process.env.NEXT_PUBLIC_STRIPE && !user.parentSubscriptionId && (
|
||||||
<fieldset className="border rounded-md p-2 border-primary">
|
<fieldset className="border rounded-md p-2 border-primary">
|
||||||
<legend className="px-3 py-1 text-sm sm:text-base border rounded-md border-primary">
|
<legend className="px-3 py-1 text-sm sm:text-base border rounded-md border-primary">
|
||||||
<b>{t("optional")}</b> <i>{t("feedback_help")}</i>
|
<b>{t("optional")}</b> <i>{t("feedback_help")}</i>
|
||||||
|
|
|
@ -9,8 +9,6 @@ import getServerSideProps from "@/lib/client/getServerSideProps";
|
||||||
import { Trans, useTranslation } from "next-i18next";
|
import { Trans, useTranslation } from "next-i18next";
|
||||||
import { useUser } from "@/hooks/store/user";
|
import { useUser } from "@/hooks/store/user";
|
||||||
|
|
||||||
const stripeEnabled = process.env.NEXT_PUBLIC_STRIPE === "true";
|
|
||||||
|
|
||||||
export default function Subscribe() {
|
export default function Subscribe() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [submitLoader, setSubmitLoader] = useState(false);
|
const [submitLoader, setSubmitLoader] = useState(false);
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "Collection" DROP CONSTRAINT "Collection_createdById_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "Link" DROP CONSTRAINT "Link_createdById_fkey";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Collection" ALTER COLUMN "createdById" DROP NOT NULL;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Link" ALTER COLUMN "createdById" DROP NOT NULL;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Collection" ADD CONSTRAINT "Collection_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Link" ADD CONSTRAINT "Link_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
@ -108,8 +108,8 @@ model Collection {
|
||||||
owner User @relation(fields: [ownerId], references: [id])
|
owner User @relation(fields: [ownerId], references: [id])
|
||||||
ownerId Int
|
ownerId Int
|
||||||
members UsersAndCollections[]
|
members UsersAndCollections[]
|
||||||
createdBy User @relation("CreatedCollections", fields: [createdById], references: [id])
|
createdBy User? @relation("CreatedCollections", fields: [createdById], references: [id])
|
||||||
createdById Int
|
createdById Int?
|
||||||
links Link[]
|
links Link[]
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @default(now()) @updatedAt
|
updatedAt DateTime @default(now()) @updatedAt
|
||||||
|
@ -138,8 +138,8 @@ model Link {
|
||||||
type String @default("url")
|
type String @default("url")
|
||||||
description String @default("")
|
description String @default("")
|
||||||
pinnedBy User[] @relation("PinnedLinks")
|
pinnedBy User[] @relation("PinnedLinks")
|
||||||
createdBy User @relation("CreatedLinks", fields: [createdById], references: [id])
|
createdBy User? @relation("CreatedLinks", fields: [createdById], references: [id])
|
||||||
createdById Int
|
createdById Int?
|
||||||
collection Collection @relation(fields: [collectionId], references: [id])
|
collection Collection @relation(fields: [collectionId], references: [id])
|
||||||
collectionId Int
|
collectionId Int
|
||||||
tags Tag[]
|
tags Tag[]
|
||||||
|
|
Ŝarĝante…
Reference in New Issue