// database/migrations/xxxx_xx_xx_create_custom_products_table.php
Schema::create('custom_products', function (Blueprint $table) {
    $table->id();
    $table->string('master_id')->nullable();
    $table->string('jewelry_type')->nullable(); // ring/earring/pendant
    $table->string('shape')->nullable();
    $table->string('head_style')->nullable();
    $table->string('shank_style')->nullable();
    $table->string('metal_head')->nullable();
    $table->string('shank_metals')->nullable();
    $table->string('ring_size')->nullable();
    $table->string('carat_size')->nullable();
    $table->string('image_path')->nullable();
    $table->string('shopify_product_id')->nullable();
    $table->string('shopify_handle')->nullable();
    $table->timestamps();
});

// routes/web.php
Route::post('/jewelry/create-custom-product', [JewelryController::class, 'createCustomProduct'])
    ->name('jewelry.create-custom-product');

    use App\Models\CustomProduct;
use Illuminate\Support\Facades\Http;

public function createCustomProduct(Request $request)
{
    $request->validate([
        'screenshot' => 'nullable|string', // base64 data URL
    ]);

    // 1. Save screenshot as file
    $imagePath = null;
    $base64Attachment = null;

    if ($request->screenshot) {
        $imageData = preg_replace('#^data:image/\w+;base64,#i', '', $request->screenshot);
        $base64Attachment = $imageData; // Shopify accepts raw base64
        $imageData = base64_decode($imageData);

        $fileName = 'custom360/' . uniqid() . '.png';
        \Storage::disk('public')->put($fileName, $imageData);
        $imagePath = $fileName;
    }

    // 2. Save to local DB
    $customProduct = CustomProduct::create([
        'master_id'     => $request->master_id,
        'jewelry_type'  => $request->jewelry_type,
        'shape'         => $request->shape,
        'head_style'    => $request->head_style,
        'shank_style'   => $request->shank_style,
        'metal_head'    => $request->metal_head,
        'shank_metals'  => $request->shank_metals,
        'ring_size'     => $request->ring_size,
        'carat_size'    => $request->carat_size,
        'image_path'    => $imagePath,
    ]);

    // 3. Create product on Shopify
    $shopDomain  = config('services.shopify.domain');   // e.g. yourstore.myshopify.com
    $accessToken = config('services.shopify.token');

    $productPayload = [
        'product' => [
            'title'        => trim(($request->shank_style ?? '') . ' ' . ($request->head_style ?? '')),
            'body_html'    => "Custom built ring - Shape: {$request->shape}, Style: {$request->shank_style}, Metal: {$request->metal_head}, Size: {$request->ring_size}, Carat: {$request->carat_size}",
            'vendor'       => 'Custom360 Builder',
            'product_type' => 'Custom Jewelry',
            'tags'         => 'custom360',
            'variants'     => [[
                'price' => $request->price ?? '0.00',
                'sku'   => 'C360-' . $customProduct->id,
            ]],
        ]
    ];

    if ($base64Attachment) {
        $productPayload['product']['images'] = [[
            'attachment' => $base64Attachment
        ]];
    }

    $response = Http::withHeaders([
        'X-Shopify-Access-Token' => $accessToken,
        'Content-Type' => 'application/json',
    ])->post("https://{$shopDomain}/admin/api/2024-01/products.json", $productPayload);

    if ($response->successful()) {
        $shopifyProduct = $response->json('product');
        $customProduct->update([
            'shopify_product_id' => $shopifyProduct['id'],
            'shopify_handle'      => $shopifyProduct['handle'],
        ]);

        return response()->json([
            'status'  => true,
            'message' => 'Product created successfully',
            'product' => $customProduct,
            'shopify' => $shopifyProduct,
        ]);
    }

    return response()->json([
        'status'  => false,
        'message' => 'Shopify product creation failed',
        'error'   => $response->json(),
    ], 422);
}


<button type="button" class="btn btn-dark mt-3" id="createProductBtn">
    Create Product
</button>

document.getElementById('createProductBtn').addEventListener('click', async function () {
    // Reuse takeScreenshot logic to capture 360 preview
    await takeScreenshot(); // yeh already screenshotInput field fill karta hai

    const screenshot = document.getElementById('screenshotInput').value;

    const payload = {
        master_id     : document.getElementById('master_id').value,
        jewelry_type  : $('#jewelryMenu li.active').data('type'),
        shape         : window.filters['shape'],
        head_style    : window.filters['head_style'],
        shank_style   : window.filters['shank_style'],
        metal_head    : window.filters['metal_head'],
        shank_metals  : window.filters['shank_metals'],
        ring_size     : window.filters['ring_size'],
        carat_size    : window.filters['carat_size'],
        screenshot    : screenshot,
        _token        : getCsrfToken()
    };

    $.ajax({
        url: "{{ route('jewelry.create-custom-product') }}",
        method: 'POST',
        data: payload,
        beforeSend: function () {
            $('#createProductBtn').prop('disabled', true).text('Creating...');
        },
        success: function (res) {
            if (res.status) {
                alert('Product created! Shopify ID: ' + res.shopify.id);
            } else {
                alert(res.message);
            }
        },
        error: function (xhr) {
            console.error(xhr.responseText);
            alert('Something went wrong.');
        },
        complete: function () {
            $('#createProductBtn').prop('disabled', false).text('Create Product');
        }
    });
});