drafts->createDraft($request->user(), $request->validated()); return response()->json([ 'data' => $this->presenter->card($card, true, $request->user()), ], Response::HTTP_CREATED); } public function show(Request $request, int $id): JsonResponse { $card = $this->editableCard($request, $id); return response()->json([ 'data' => $this->presenter->card($card, true, $request->user()), ]); } public function update(SaveNovaCardDraftRequest $request, int $id): JsonResponse { $card = $this->editableCard($request, $id); $card = $this->drafts->autosave($card, $request->validated()); return response()->json([ 'data' => $this->presenter->card($card, true, $request->user()), ]); } public function autosave(SaveNovaCardDraftRequest $request, int $id): JsonResponse { $card = $this->editableCard($request, $id); $card = $this->drafts->autosave($card, $request->validated()); return response()->json([ 'data' => $this->presenter->card($card, true, $request->user()), 'meta' => [ 'saved_at' => now()->toISOString(), ], ]); } public function background(UploadNovaCardBackgroundRequest $request, int $id): JsonResponse { $card = $this->editableCard($request, $id); $background = $this->backgrounds->storeUploadedBackground($request->user(), $request->file('background')); $card = $this->drafts->autosave($card, [ 'background_type' => 'upload', 'background_image_id' => $background->id, 'project_json' => [ 'background' => [ 'type' => 'upload', 'background_image_id' => $background->id, ], ], ]); event(new NovaCardBackgroundUploaded($card, $background)); return response()->json([ 'data' => $this->presenter->card($card, true, $request->user()), 'background' => [ 'id' => (int) $background->id, 'processed_url' => $background->processedUrl(), 'width' => (int) $background->width, 'height' => (int) $background->height, ], ], Response::HTTP_CREATED); } public function render(Request $request, int $id): JsonResponse { $card = $this->editableCard($request, $id); $result = $this->renders->render($card->loadMissing('backgroundImage')); return response()->json([ 'data' => $this->presenter->card($card->fresh()->loadMissing(['user.profile', 'category', 'template', 'backgroundImage', 'tags']), true, $request->user()), 'render' => $result, ]); } public function publish(SaveNovaCardDraftRequest $request, int $id): JsonResponse { $card = $this->editableCard($request, $id); if ($request->validated() !== []) { $card = $this->drafts->autosave($card, $request->validated()); } if (trim((string) $card->title) === '' || trim((string) $card->quote_text) === '') { return response()->json([ 'message' => 'Title and quote text are required before publishing.', ], Response::HTTP_UNPROCESSABLE_ENTITY); } $card = $this->publishes->publishNow($card->loadMissing('backgroundImage')); event(new NovaCardPublished($card)); return response()->json([ 'data' => $this->presenter->card($card, true, $request->user()), ]); } public function destroy(Request $request, int $id): JsonResponse { $card = $this->editableCard($request, $id); if ($card->status === NovaCard::STATUS_PUBLISHED && in_array($card->visibility, [NovaCard::VISIBILITY_PUBLIC, NovaCard::VISIBILITY_UNLISTED], true)) { return response()->json([ 'message' => 'Published cards cannot be deleted from the draft API.', ], Response::HTTP_UNPROCESSABLE_ENTITY); } $card->delete(); return response()->json([ 'ok' => true, ]); } private function editableCard(Request $request, int $id): NovaCard { return NovaCard::query() ->with(['user.profile', 'category', 'template', 'backgroundImage', 'tags']) ->where('user_id', $request->user()->id) ->findOrFail($id); } }