-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from harishdeivanayagam/feature/cloud-host-license
feat: cloud host license
- Loading branch information
Showing
12 changed files
with
387 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
The Rowfill Enterprise license (the “Enterprise License”) | ||
Copyright (c) 2024-2025 Harish Deivanayagam. | ||
|
||
With regard to the Rowfill Software: | ||
|
||
This software and associated documentation files (the "Software") may only be | ||
used in production, if you (and any entity that you represent) have agreed to, | ||
and are in compliance with, the Rowfill Subscription Terms of Service, available | ||
at https://cloud.rowfill.com/terms (the “Enterprise Terms”), or other | ||
agreement governing the use of the Software, as agreed by you and Rowfill, | ||
and otherwise have a valid Rowfill Enterprise license for the | ||
correct number of user seats. Subject to the foregoing sentence, you are free to | ||
modify this Software and publish patches to the Software. You agree that Rowfill | ||
and/or its licensors (as applicable) retain all right, title and interest in and | ||
to all such modifications and/or patches, and all such modifications and/or | ||
patches may only be used, copied, modified, displayed, distributed, or otherwise | ||
exploited with a valid Rowfill Enterprise license for the correct | ||
number of user seats. Notwithstanding the foregoing, you may copy and modify | ||
the Software for development and testing purposes, without requiring a | ||
subscription. You agree that Rowfill and/or its licensors (as applicable) retain | ||
all right, title and interest in and to all such modifications. You are not | ||
granted any other rights beyond what is expressly stated herein. Subject to the | ||
foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, | ||
and/or sell the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
|
||
For all third party components incorporated into the Rowfill Software, those | ||
components are licensed under the original license provided by the owner of the | ||
applicable component. |
15 changes: 15 additions & 0 deletions
15
prisma/migrations/20250117105538_billing_credits/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
-- CreateTable | ||
CREATE TABLE "Billing" ( | ||
"organizationId" TEXT NOT NULL, | ||
"credits" INTEGER NOT NULL DEFAULT 1000, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "Billing_pkey" PRIMARY KEY ("organizationId") | ||
); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "Billing_organizationId_key" ON "Billing"("organizationId"); | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Billing" ADD CONSTRAINT "Billing_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE; |
6 changes: 6 additions & 0 deletions
6
prisma/migrations/20250117113005_update_billing_table/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
-- CreateEnum | ||
CREATE TYPE "Plan" AS ENUM ('FREE', 'PRO', 'ENTERPRISE'); | ||
|
||
-- AlterTable | ||
ALTER TABLE "Billing" ADD COLUMN "expiresAt" TIMESTAMP(3), | ||
ADD COLUMN "plan" "Plan" NOT NULL DEFAULT 'FREE'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
"use server" | ||
|
||
import { getAuthToken } from "@/lib/auth" | ||
import { prisma } from "@/lib/prisma" | ||
|
||
export async function getBillingAndCreateIfNotExists() { | ||
const { organizationId } = await getAuthToken() | ||
|
||
const cloudHosted = process.env.EE_ENABLED && process.env.EE_ENABLED === "true" | ||
|
||
if (!cloudHosted) { | ||
return null | ||
} | ||
|
||
let billing = await prisma.billing.findFirst({ | ||
where: { | ||
organizationId: organizationId | ||
} | ||
}) | ||
|
||
if (!billing && process.env.EE_ENABLED && process.env.EE_ENABLED === "true") { | ||
await prisma.billing.create({ | ||
data: { | ||
organizationId: organizationId | ||
} | ||
}) | ||
|
||
billing = await prisma.billing.findFirst({ | ||
where: { | ||
organizationId: organizationId | ||
} | ||
}) | ||
} | ||
|
||
return billing | ||
} | ||
|
||
export async function getPlans() { | ||
|
||
const cloudHosted = process.env.EE_ENABLED && process.env.EE_ENABLED === "true" | ||
|
||
if (!cloudHosted) { | ||
return [] | ||
} | ||
|
||
// TODO: Implement plans | ||
return [ | ||
{ | ||
name: "FREE", | ||
price: "0", | ||
credits: "1000", | ||
for: "lifetime", | ||
purchaseUrl: "", | ||
}, | ||
{ | ||
name: "PRO_MONTHLY", | ||
price: "35", | ||
credits: "15000", | ||
for: "monthly", | ||
purchaseUrl: "", // TODO: Stripe Link | ||
}, | ||
{ | ||
name: "PRO_YEARLY", | ||
price: "350", | ||
credits: "15000", | ||
for: "yearly", | ||
purchaseUrl: "", // TODO: Stripe Link | ||
}, | ||
{ | ||
name: "ENTERPRISE", | ||
price: "Custom", | ||
credits: "100000+", | ||
for: "Contract", | ||
purchaseUrl: "", // TODO: Calendar Link | ||
} | ||
] | ||
} | ||
|
||
export async function handleDowngradeToFree() { | ||
const { organizationId } = await getAuthToken() | ||
|
||
await prisma.billing.update({ | ||
where: { | ||
organizationId: organizationId | ||
}, | ||
data: { | ||
plan: "FREE" | ||
} | ||
}) | ||
|
||
return true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
"use client" | ||
|
||
import { Billing } from "@prisma/client" | ||
import { useEffect, useState } from "react" | ||
import { getBillingAndCreateIfNotExists, getPlans, handleDowngradeToFree } from "./actions" | ||
import { Button } from "@/components/ui/button" | ||
import { useToast } from "@/hooks/use-toast" | ||
import { useRouter } from "next/navigation" | ||
|
||
export default function BillingComponent() { | ||
|
||
type Plan = { | ||
name: string | ||
price: string | ||
credits: string | ||
for: string | ||
purchaseUrl: string | ||
} | ||
|
||
const [billing, setBilling] = useState<Billing | null>(null) | ||
const [plans, setPlans] = useState<Plan[]>([]) | ||
const { toast } = useToast() | ||
const router = useRouter() | ||
|
||
useEffect(() => { | ||
fetchData() | ||
}, []) | ||
|
||
const fetchData = async () => { | ||
const billing = await getBillingAndCreateIfNotExists() | ||
const plans = await getPlans() | ||
setBilling(billing) | ||
setPlans(plans) | ||
} | ||
|
||
const planButtonText = (plan: Plan) => { | ||
if (billing && billing.plan === plan.name) { | ||
return "Current Plan" | ||
} | ||
|
||
if (billing && billing.plan === "PRO" && plan.name === "FREE") { | ||
return "Downgrade" | ||
} | ||
|
||
if (billing && billing.plan === "FREE" && plan.name.includes("PRO_")) { | ||
return "Upgrade" | ||
} | ||
|
||
if (billing && billing.plan === "ENTERPRISE") { | ||
return "Contact Support" | ||
} | ||
|
||
return "Contact Support" | ||
} | ||
|
||
const handlePlanButton = async (plan: Plan) => { | ||
if (billing && billing.plan === "FREE" && plan.name !== "FREE") { | ||
router.push(plan.purchaseUrl) | ||
return | ||
} | ||
|
||
if (billing && (billing.plan === "FREE" || billing.plan === "PRO") && plan.name === "ENTERPRISE") { | ||
router.push(plan.purchaseUrl) | ||
return | ||
} | ||
|
||
if (billing && (billing.plan.includes("PRO_")) && plan.name === "FREE") { | ||
// Handle Downgrade | ||
await handleDowngradeToFree() | ||
toast({ | ||
title: "Downgraded to Free", | ||
description: "You have been downgraded to the Free plan", | ||
}) | ||
return | ||
} | ||
|
||
toast({ | ||
title: "Failed to update plan", | ||
description: "Please contact support", | ||
variant: "destructive", | ||
}) | ||
} | ||
|
||
return ( | ||
<div> | ||
{/* TODO: Billing goes here */} | ||
{plans.map((plan, index) => ( | ||
<div key={`plan-${index}`} className="flex justify-between items-center p-2 rounded-md border-b-[1px] border-gray-200"> | ||
<div className="flex items-center gap-3"> | ||
<p className="text-xl flex items-center gap-2 font-bold">{plan.price} / {plan.for}</p> | ||
<div className="flex flex-col gap-1"> | ||
<p className="text-lg">{plan.name}</p> | ||
<p className="text-sm">{plan.credits}/month</p> | ||
</div> | ||
</div> | ||
<Button disabled={planButtonText(plan) === "Current Plan" || planButtonText(plan) === "Contact Support"} onClick={() => handlePlanButton(plan)}>{planButtonText(plan)}</Button> | ||
</div> | ||
))} | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
export default function ConsoleDashboard() { | ||
return <div className="flex items-center justify-center h-screen text-2xl font-bold">Console</div> | ||
return <div className="flex items-center justify-center h-screen text-sm text-muted-foreground">No sheets found</div> | ||
} |
Oops, something went wrong.