Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { collection } from "@/lib/collections";
import type { CustomDomain } from "@/lib/collections/deploy/custom-domains";
import type { Deployment } from "@/lib/collections/deploy/deployments";
import type { Domain } from "@/lib/collections/deploy/domains";
import type { Environment } from "@/lib/collections/deploy/environments";
Expand All @@ -18,10 +19,12 @@ type ProjectDataContextType = {
domains: Domain[];
deployments: Deployment[];
environments: Environment[];
customDomains: CustomDomain[];

isDomainsLoading: boolean;
isDeploymentsLoading: boolean;
isEnvironmentsLoading: boolean;
isCustomDomainsLoading: boolean;

getDomainsForDeployment: (deploymentId: string) => Domain[];
getLiveDomains: () => Domain[];
Expand All @@ -30,6 +33,7 @@ type ProjectDataContextType = {

refetchDomains: () => void;
refetchDeployments: () => void;
refetchCustomDomains: () => void;
refetchAll: () => void;
};

Expand Down Expand Up @@ -80,10 +84,20 @@ export const ProjectDataProvider = ({ children }: PropsWithChildren) => {
[projectId],
);

const customDomainsQuery = useLiveQuery(
(q) =>
q
.from({ customDomain: collection.customDomains })
.where(({ customDomain }) => eq(customDomain.projectId, projectId))
.orderBy(({ customDomain }) => customDomain.createdAt, "desc"),
[projectId],
);

const value = useMemo(() => {
const domains = domainsQuery.data ?? [];
const deployments = deploymentsQuery.data ?? [];
const environments = environmentsQuery.data ?? [];
const customDomains = customDomainsQuery.data ?? [];
const project = projectQuery.data?.at(0);

return {
Expand All @@ -101,6 +115,9 @@ export const ProjectDataProvider = ({ children }: PropsWithChildren) => {
environments,
isEnvironmentsLoading: environmentsQuery.isLoading,

customDomains,
isCustomDomainsLoading: customDomainsQuery.isLoading,

getDomainsForDeployment: (deploymentId: string) =>
domains.filter((d) => d.deploymentId === deploymentId),

Expand All @@ -113,14 +130,23 @@ export const ProjectDataProvider = ({ children }: PropsWithChildren) => {

refetchDomains: () => collection.domains.utils.refetch(),
refetchDeployments: () => collection.deployments.utils.refetch(),
refetchCustomDomains: () => collection.customDomains.utils.refetch(),
refetchAll: () => {
collection.projects.utils.refetch();
collection.deployments.utils.refetch();
collection.domains.utils.refetch();
collection.environments.utils.refetch();
collection.customDomains.utils.refetch();
},
};
}, [projectId, domainsQuery, deploymentsQuery, projectQuery, environmentsQuery]);
}, [
projectId,
domainsQuery,
deploymentsQuery,
projectQuery,
environmentsQuery,
customDomainsQuery,
]);

return <ProjectDataContext.Provider value={value}>{children}</ProjectDataContext.Provider>;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";
import { trpc } from "@/lib/trpc/client";
import { collection } from "@/lib/collections";
import { cn } from "@/lib/utils";
import {
Button,
Expand All @@ -9,7 +9,6 @@ import {
SelectItem,
SelectTrigger,
SelectValue,
toast,
} from "@unkey/ui";
import { useEffect, useRef, useState } from "react";
import { useProjectData } from "../../data-provider";
Expand All @@ -32,18 +31,15 @@ function extractDomain(input: string): string {
type AddCustomDomainProps = {
environments: Array<{ id: string; slug: string }>;
getExistingDomain: (domain: string) => CustomDomain | undefined;
onCancel: () => void;
onSuccess: () => void;
onDismiss: () => void;
};

export function AddCustomDomain({
environments,
getExistingDomain,
onCancel,
onSuccess,
onDismiss,
}: AddCustomDomainProps) {
const { projectId } = useProjectData();
const addMutation = trpc.deploy.customDomain.add.useMutation();
const containerRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);

Expand All @@ -61,8 +57,6 @@ export function AddCustomDomain({
inputRef.current?.focus();
}, []);

const isSubmitting = addMutation.isLoading;

const getError = (): string | undefined => {
if (!domain) {
return undefined;
Expand All @@ -83,41 +77,37 @@ export function AddCustomDomain({
const isValid = domain && !error && environmentId;

const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Enter" && isValid && !isSubmitting) {
if (e.key === "Enter" && isValid) {
e.preventDefault();
handleSave();
} else if (e.key === "Escape") {
onCancel();
onDismiss();
}
};

const handleSave = async () => {
if (!isValid || isSubmitting) {
const handleSave = () => {
if (!isValid) {
return;
}

const mutation = addMutation.mutateAsync({
collection.customDomains.insert({
id: crypto.randomUUID(),
domain,
workspaceId: "",
projectId,
environmentId,
domain,
});

toast.promise(mutation, {
loading: "Adding domain...",
success: (data) => ({
message: "Domain added",
description: `Add a CNAME record pointing to ${data.targetCname}`,
}),
error: (err) => ({
message: "Failed to add domain",
description: err.message,
}),
verificationStatus: "pending",
verificationToken: "",
ownershipVerified: false,
cnameVerified: false,
targetCname: "",
checkAttempts: 0,
lastCheckedAt: null,
verificationError: null,
createdAt: Date.now(),
updatedAt: null,
});

try {
await mutation;
onSuccess();
} catch {}
onDismiss();
};

return (
Expand Down Expand Up @@ -154,17 +144,11 @@ export function AddCustomDomain({
variant="primary"
onClick={handleSave}
className="h-8 text-xs px-3"
disabled={!isValid || isSubmitting}
loading={isSubmitting}
disabled={!isValid}
>
Add
</Button>
<Button
variant="ghost"
onClick={onCancel}
disabled={isSubmitting}
className="h-8 text-xs px-3"
>
<Button variant="ghost" onClick={onDismiss} className="h-8 text-xs px-3">
Cancel
</Button>
</div>
Expand Down
Loading