user()->portfolios; return ApiResponse::success($portfolios); } public function store(Request $request) { $validated = $request->validate([ 'name' => 'required|string|max:255', 'domain' => 'required|string|max:255|unique:portfolios,domain', ]); $portfolio = auth()->user()->portfolios()->create($validated); return ApiResponse::success($portfolio, 'Portfolio created', 201); } public function show(Portfolio $portfolio) { $this->authorize('view', $portfolio); return ApiResponse::success($portfolio); } public function update(Request $request, Portfolio $portfolio) { $this->authorize('update', $portfolio); $validated = $request->validate([ 'name' => 'sometimes|string|max:255', 'domain' => 'sometimes|string|max:255|unique:portfolios,domain,' . $portfolio->id, ]); $portfolio->update($validated); return ApiResponse::success($portfolio, 'Portfolio updated'); } public function destroy(Portfolio $portfolio) { $this->authorize('delete', $portfolio); $portfolio->delete(); return ApiResponse::success(null, 'Portfolio deleted'); } public function upload(Request $request, Portfolio $portfolio, PortfolioUploadService $uploadService) { $this->authorize('upload', $portfolio); $request->validate([ 'file' => 'required|file|max:10240', // Max 10MB ]); $uploadService->upload($request->file('file'), $portfolio); return ApiResponse::success(null, 'ZIP uploaded successfully'); } public function deploy(Request $request, Portfolio $portfolio) { $this->authorize('deploy', $portfolio); DeployStaticSiteJob::dispatch( $portfolio->getPortfolioName(), $portfolio->getPortfolioDomain(), $portfolio->id ); return ApiResponse::success( null, "Async deployment queued for '{$portfolio->getPortfolioName()}'." ); } public function randomPortfolio() { return ApiResponse::success(["host" => Portfolio::inRandomOrder()->first()->domain]); } }