195 lines
7.4 KiB
Elixir
195 lines
7.4 KiB
Elixir
|
|
defmodule SimpleshopWeb.DebugLive do
|
||
|
|
use SimpleshopWeb, :live_view
|
||
|
|
require Logger
|
||
|
|
|
||
|
|
@impl true
|
||
|
|
def mount(_params, _session, socket) do
|
||
|
|
send(self(), :fetch_shops)
|
||
|
|
|
||
|
|
{:ok,
|
||
|
|
socket
|
||
|
|
|> assign(:loading, true)
|
||
|
|
|> assign(:shops, [])
|
||
|
|
|> assign(:error, nil)
|
||
|
|
|> assign(:response_details, nil)}
|
||
|
|
end
|
||
|
|
|
||
|
|
@impl true
|
||
|
|
def handle_info(:fetch_shops, socket) do
|
||
|
|
config = Application.get_env(:simpleshop, :printify)
|
||
|
|
token = Keyword.get(config, :access_token)
|
||
|
|
|
||
|
|
if token && token != "your_personal_access_token_here" do
|
||
|
|
url = "https://api.printify.com/v1/shops.json"
|
||
|
|
|
||
|
|
# Try without the Content-Type header - some APIs don't like it for GET requests
|
||
|
|
headers = [
|
||
|
|
{"Authorization", "Bearer #{token}"},
|
||
|
|
{"User-Agent", "SimpleshopMVP"}
|
||
|
|
]
|
||
|
|
|
||
|
|
Logger.info("Making request to: #{url}")
|
||
|
|
Logger.info("Token (first 20 chars): #{String.slice(token, 0, 20)}...")
|
||
|
|
|
||
|
|
case Req.get(url, headers: headers) do
|
||
|
|
{:ok, %{status: 200, body: shops}} ->
|
||
|
|
Logger.info("Successfully fetched #{length(shops)} shops")
|
||
|
|
|
||
|
|
{:noreply,
|
||
|
|
socket
|
||
|
|
|> assign(:loading, false)
|
||
|
|
|> assign(:shops, shops)
|
||
|
|
|> assign(:error, nil)
|
||
|
|
|> assign(:response_details, nil)}
|
||
|
|
|
||
|
|
{:ok, %{status: status, body: body, headers: resp_headers}} ->
|
||
|
|
Logger.error("Failed to fetch shops: #{status}")
|
||
|
|
Logger.error("Response body: #{inspect(body)}")
|
||
|
|
Logger.error("Response headers: #{inspect(resp_headers)}")
|
||
|
|
|
||
|
|
error_msg = case body do
|
||
|
|
%{"errors" => errors} -> "API Error: #{inspect(errors)}"
|
||
|
|
%{"message" => message} -> "API Error: #{message}"
|
||
|
|
_ -> inspect(body)
|
||
|
|
end
|
||
|
|
|
||
|
|
{:noreply,
|
||
|
|
socket
|
||
|
|
|> assign(:loading, false)
|
||
|
|
|> assign(:error, "HTTP #{status}: Authentication failed")
|
||
|
|
|> assign(:response_details, %{
|
||
|
|
status: status,
|
||
|
|
body: body,
|
||
|
|
error_msg: error_msg
|
||
|
|
})}
|
||
|
|
|
||
|
|
{:error, error} ->
|
||
|
|
Logger.error("HTTP error fetching shops: #{inspect(error)}")
|
||
|
|
|
||
|
|
{:noreply,
|
||
|
|
socket
|
||
|
|
|> assign(:loading, false)
|
||
|
|
|> assign(:error, "Network error: #{inspect(error)}")
|
||
|
|
|> assign(:response_details, nil)}
|
||
|
|
end
|
||
|
|
else
|
||
|
|
{:noreply,
|
||
|
|
socket
|
||
|
|
|> assign(:loading, false)
|
||
|
|
|> assign(:error, "Access token not configured. Please add it to config/dev.exs")
|
||
|
|
|> assign(:response_details, nil)}
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
@impl true
|
||
|
|
def render(assigns) do
|
||
|
|
~H"""
|
||
|
|
<div class="mx-auto max-w-4xl py-12 px-4">
|
||
|
|
<h1 class="text-3xl font-bold mb-8">Printify Shop Information</h1>
|
||
|
|
|
||
|
|
<%= if @loading do %>
|
||
|
|
<div class="text-center py-12">
|
||
|
|
<div class="animate-spin rounded-full h-16 w-16 border-b-2 border-blue-600 mx-auto"></div>
|
||
|
|
<p class="text-gray-600 mt-4">Fetching your shop information...</p>
|
||
|
|
</div>
|
||
|
|
<% else %>
|
||
|
|
<%= if @error do %>
|
||
|
|
<div class="bg-red-50 border border-red-200 rounded-lg p-6 mb-6">
|
||
|
|
<h2 class="text-lg font-semibold text-red-800 mb-2">Error</h2>
|
||
|
|
<p class="text-red-700 mb-4"><%= @error %></p>
|
||
|
|
|
||
|
|
<%= if @response_details do %>
|
||
|
|
<div class="mt-4 p-4 bg-white rounded border border-red-300">
|
||
|
|
<p class="text-sm font-semibold text-gray-700 mb-2">Debug Information:</p>
|
||
|
|
<div class="text-xs text-gray-600 space-y-2">
|
||
|
|
<p><strong>Status Code:</strong> <%= @response_details.status %></p>
|
||
|
|
<p><strong>Error Message:</strong> <%= @response_details.error_msg %></p>
|
||
|
|
<details class="mt-2">
|
||
|
|
<summary class="cursor-pointer text-gray-700 hover:text-gray-900">Full Response Body</summary>
|
||
|
|
<pre class="mt-2 bg-gray-100 p-2 rounded overflow-auto text-xs"><%= Jason.encode!(@response_details.body, pretty: true) %></pre>
|
||
|
|
</details>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="mt-4 p-4 bg-yellow-50 rounded border border-yellow-300">
|
||
|
|
<p class="text-sm font-semibold text-yellow-900 mb-2">Troubleshooting Tips:</p>
|
||
|
|
<ul class="text-xs text-yellow-800 space-y-1 list-disc list-inside">
|
||
|
|
<li>Make sure you copied the FULL token (it's very long)</li>
|
||
|
|
<li>Check that there are no extra spaces before or after the token</li>
|
||
|
|
<li>The token should start with "eyJ"</li>
|
||
|
|
<li>Make sure the token hasn't expired</li>
|
||
|
|
<li>Try creating a new Personal Access Token in Printify</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
<% end %>
|
||
|
|
</div>
|
||
|
|
<% else %>
|
||
|
|
<%= if @shops == [] do %>
|
||
|
|
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-6">
|
||
|
|
<p class="text-yellow-800">No shops found for this account.</p>
|
||
|
|
</div>
|
||
|
|
<% else %>
|
||
|
|
<div class="space-y-6">
|
||
|
|
<%= for shop <- @shops do %>
|
||
|
|
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
|
||
|
|
<div class="mb-4 pb-4 border-b">
|
||
|
|
<h2 class="text-2xl font-bold text-gray-900"><%= shop["title"] %></h2>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
|
|
<div class="bg-green-50 border border-green-200 rounded-lg p-4">
|
||
|
|
<p class="text-sm font-semibold text-green-900 mb-2">Shop ID (Use this!)</p>
|
||
|
|
<p class="text-2xl font-mono font-bold text-green-700">
|
||
|
|
<%= shop["id"] %>
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="space-y-2">
|
||
|
|
<div>
|
||
|
|
<p class="text-sm font-medium text-gray-600">Sales Channel</p>
|
||
|
|
<p class="text-gray-900"><%= shop["sales_channel"] || "N/A" %></p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="mt-6 p-4 bg-blue-50 rounded-lg">
|
||
|
|
<p class="text-sm text-blue-800">
|
||
|
|
<strong>Next step:</strong> Copy the Shop ID above and paste it into
|
||
|
|
<code class="bg-blue-100 px-2 py-1 rounded">config/dev.exs</code>
|
||
|
|
</p>
|
||
|
|
<pre class="mt-2 text-xs bg-blue-100 p-2 rounded overflow-x-auto">shop_id: "<%= shop["id"] %>",</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<details class="mt-4">
|
||
|
|
<summary class="cursor-pointer text-sm text-gray-600 hover:text-gray-800">
|
||
|
|
View full shop details (JSON)
|
||
|
|
</summary>
|
||
|
|
<pre class="mt-2 bg-gray-100 p-4 rounded-lg overflow-auto text-xs"><%= Jason.encode!(shop, pretty: true) %></pre>
|
||
|
|
</details>
|
||
|
|
</div>
|
||
|
|
<% end %>
|
||
|
|
</div>
|
||
|
|
<% end %>
|
||
|
|
<% end %>
|
||
|
|
|
||
|
|
<div class="mt-8 flex gap-4">
|
||
|
|
<.link
|
||
|
|
navigate={~p"/"}
|
||
|
|
class="inline-block bg-gray-600 text-white px-6 py-2 rounded-lg hover:bg-gray-700"
|
||
|
|
>
|
||
|
|
← Back to Home
|
||
|
|
</.link>
|
||
|
|
|
||
|
|
<.link
|
||
|
|
navigate={~p"/products"}
|
||
|
|
class="inline-block bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700"
|
||
|
|
>
|
||
|
|
View Products →
|
||
|
|
</.link>
|
||
|
|
</div>
|
||
|
|
<% end %>
|
||
|
|
</div>
|
||
|
|
"""
|
||
|
|
end
|
||
|
|
end
|