this repo has no description
1"use client";
2
3import { useState, useEffect } from "react";
4import { useRouter } from "next/navigation";
5
6interface MasterOwnerProfile {
7 name: string;
8}
9
10export function MasterOwnerForm() {
11 const router = useRouter();
12 const [name, setName] = useState("");
13 const [loading, setLoading] = useState(false);
14 const [error, setError] = useState<string | null>(null);
15 const [existingOwner, setExistingOwner] = useState<MasterOwnerProfile | null>(null);
16 const [existingOwnerUri, setExistingOwnerUri] = useState<string | null>(null);
17 const [isLoadingOwner, setIsLoadingOwner] = useState(true);
18 const [isEditing, setIsEditing] = useState(false);
19 const [showDeleteModal, setShowDeleteModal] = useState(false);
20
21 async function handleDelete() {
22 if (!existingOwnerUri) {
23 setError("Missing master owner URI");
24 return;
25 }
26
27 setLoading(true);
28 setError(null);
29
30 try {
31 const res = await fetch("/api/master-owner", {
32 method: "DELETE",
33 headers: { "Content-Type": "application/json" },
34 body: JSON.stringify({ uri: existingOwnerUri }),
35 });
36
37 if (!res.ok) {
38 const data = await res.json();
39 throw new Error(data.error || "Failed to delete master owner");
40 }
41
42 setExistingOwner(null);
43 setExistingOwnerUri(null);
44 setIsEditing(false);
45 setShowDeleteModal(false);
46 setName("");
47 router.refresh();
48 } catch (err) {
49 console.error("Failed to delete master owner:", err);
50 setError((err as Error).message || "Failed to delete master owner");
51 } finally {
52 setLoading(false);
53 }
54 }
55
56 // Fetch existing master owner profile on mount
57 useEffect(() => {
58 async function fetchOwner() {
59 try {
60 const res = await fetch("/api/master-owner");
61 if (!res.ok) {
62 throw new Error("Failed to fetch master owner");
63 }
64 const data = await res.json();
65 if (data.masterOwner) {
66 setExistingOwner(data.masterOwner);
67 setExistingOwnerUri(typeof data.uri === "string" ? data.uri : null);
68 }
69 } catch (err) {
70 console.error("Failed to fetch master owner:", err);
71 } finally {
72 setIsLoadingOwner(false);
73 }
74 }
75
76 fetchOwner();
77 }, []);
78
79 async function handleSubmit(e: React.FormEvent) {
80 e.preventDefault();
81 setLoading(true);
82 setError(null);
83
84 try {
85 const method = isEditing ? "PUT" : "POST";
86 const res = await fetch("/api/master-owner", {
87 method,
88 headers: { "Content-Type": "application/json" },
89 body: JSON.stringify(isEditing ? { uri: existingOwnerUri, name } : { name }),
90 });
91
92 if (!res.ok) {
93 throw new Error("Failed to update master owner");
94 }
95
96 const data = await res.json();
97 if (data.masterOwner) {
98 setExistingOwner(data.masterOwner);
99 setExistingOwnerUri(data.uri || existingOwnerUri);
100 }
101
102 setIsEditing(false);
103 setName("");
104
105 router.refresh();
106 } catch (err) {
107 console.error("Failed to update master owner:", err);
108 setError((err as Error).message || "Failed to save master owner");
109 } finally {
110 setLoading(false);
111 }
112 }
113
114 // Show loading state while fetching owner
115 if (isLoadingOwner) {
116 return <div className="text-zinc-500">Loading master owner profile...</div>;
117 }
118
119 // Show existing owner profile
120 if (existingOwner && !isEditing) {
121 return (
122 <div className="space-y-4">
123 <div className="p-4 bg-green-50 dark:bg-green-900/20 rounded-lg border border-green-200 dark:border-green-800">
124 <h3 className="text-sm font-medium text-green-900 dark:text-green-100 mb-2">
125 Master Owner Profile Found
126 </h3>
127 <p className="mb-3 text-xs italic text-green-700 dark:text-green-300/90">
128 A master owner owns the rights of the recording of a song. It is typically a record label and it generally assigns ISRC codes to recordings
129 </p>
130 <p className="text-sm text-green-800 dark:text-green-200">
131 <strong>Name:</strong> {existingOwner.name}
132 </p>
133 </div>
134 <div className="flex items-center gap-2">
135 <button
136 type="button"
137 onClick={() => {
138 setName(existingOwner.name || "");
139 setError(null);
140 setIsEditing(true);
141 }}
142 className="inline-flex py-2 px-4 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
143 disabled={loading}
144 >
145 Edit Master Owner
146 </button>
147 <button
148 type="button"
149 onClick={() => {
150 setShowDeleteModal(true);
151 }}
152 className="inline-flex py-2 px-4 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50"
153 disabled={loading}
154 >
155 {loading ? "Deleting..." : "Delete Master Owner"}
156 </button>
157 </div>
158 {error && <p className="text-red-500 text-sm">{error}</p>}
159
160 {showDeleteModal && (
161 <div className="fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50 p-4">
162 <div className="bg-white dark:bg-zinc-900 rounded-lg shadow-lg p-4 w-full max-w-sm border border-zinc-200 dark:border-zinc-800">
163 <h4 className="text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
164 Delete Master Owner?
165 </h4>
166 <p className="text-sm text-zinc-600 dark:text-zinc-400 mb-4">
167 This action cannot be undone.
168 </p>
169 <div className="flex gap-2 justify-end">
170 <button
171 type="button"
172 onClick={() => setShowDeleteModal(false)}
173 className="py-2 px-3 border border-zinc-300 dark:border-zinc-700 text-zinc-700 dark:text-zinc-300 rounded-lg hover:bg-zinc-50 dark:hover:bg-zinc-800"
174 disabled={loading}
175 >
176 Cancel
177 </button>
178 <button
179 type="button"
180 onClick={() => {
181 void handleDelete();
182 }}
183 className="py-2 px-3 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50"
184 disabled={loading}
185 >
186 {loading ? "Deleting..." : "Delete"}
187 </button>
188 </div>
189 </div>
190 </div>
191 )}
192 </div>
193 );
194 }
195
196 // Show form if no existing owner
197 return (
198 <form onSubmit={handleSubmit} className="space-y-4">
199 <div>
200 <label className="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">
201 Master owner name
202 </label>
203 <input
204 type="text"
205 value={name}
206 onChange={(e) => setName(e.target.value)}
207 className="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-700 rounded-lg bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100"
208 disabled={loading}
209 />
210 </div>
211
212 {error && <p className="text-red-500 text-sm">{error}</p>}
213
214 <div className="flex items-center gap-2">
215 <button
216 type="submit"
217 disabled={loading || !name}
218 className="inline-flex py-2 px-4 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
219 >
220 {loading ? "Saving..." : isEditing ? "Update Master Owner" : "Save Master Owner"}
221 </button>
222
223 {isEditing && (
224 <button
225 type="button"
226 onClick={() => {
227 setIsEditing(false);
228 setName("");
229 setError(null);
230 }}
231 className="inline-flex py-2 px-4 border border-zinc-300 dark:border-zinc-700 text-zinc-700 dark:text-zinc-300 rounded-lg hover:bg-zinc-50 dark:hover:bg-zinc-800"
232 >
233 Cancel
234 </button>
235 )}
236 </div>
237 </form>
238 );
239}