|
|
@@ -1,106 +1,12 @@
|
|
|
-import { useState } from "react";
|
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
-import { Input } from "@/components/ui/input";
|
|
|
-import { Label } from "@/components/ui/label";
|
|
|
-import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
|
-import { Loader2, Store, ExternalLink, CheckCircle2 } from "lucide-react";
|
|
|
-import { API_URL } from "@/lib/config";
|
|
|
-import { PhoneNumberSelector } from "./PhoneNumberSelector";
|
|
|
+import { Store, ExternalLink, Info, CheckCircle2 } from "lucide-react";
|
|
|
|
|
|
interface ShopRenterConnectProps {
|
|
|
onClose?: () => void;
|
|
|
}
|
|
|
|
|
|
export function ShopRenterConnect({ onClose }: ShopRenterConnectProps) {
|
|
|
- const [shopUrl, setShopUrl] = useState("");
|
|
|
- const [phoneNumberId, setPhoneNumberId] = useState<string>("");
|
|
|
- const [isConnecting, setIsConnecting] = useState(false);
|
|
|
- const [error, setError] = useState("");
|
|
|
- const [success, setSuccess] = useState(false);
|
|
|
-
|
|
|
- const handleConnect = async () => {
|
|
|
- setError("");
|
|
|
- setSuccess(false);
|
|
|
-
|
|
|
- // Validate shop URL
|
|
|
- if (!shopUrl.trim()) {
|
|
|
- setError("Please enter your ShopRenter shop URL");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Validate phone number selection
|
|
|
- if (!phoneNumberId) {
|
|
|
- setError("Please select a phone number for this store");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Normalize URL (remove protocol and trailing slash)
|
|
|
- let normalizedUrl = shopUrl.trim();
|
|
|
- normalizedUrl = normalizedUrl.replace(/^https?:\/\//, "");
|
|
|
- normalizedUrl = normalizedUrl.replace(/\/$/, "");
|
|
|
-
|
|
|
- // Validate URL format
|
|
|
- if (!normalizedUrl.includes(".")) {
|
|
|
- setError("Please enter a valid ShopRenter shop URL (e.g., yourshop.shoprenter.hu)");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- setIsConnecting(true);
|
|
|
-
|
|
|
- try {
|
|
|
- // Extract shopname from URL
|
|
|
- const shopname = normalizedUrl.split(".")[0];
|
|
|
-
|
|
|
- // Get auth token
|
|
|
- const sessionData = localStorage.getItem('session_data');
|
|
|
- if (!sessionData) {
|
|
|
- setError("Authentication required. Please log in again.");
|
|
|
- setIsConnecting(false);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const session = JSON.parse(sessionData);
|
|
|
-
|
|
|
- // Call the OAuth initiation Edge Function with phoneNumberId
|
|
|
- const response = await fetch(`${API_URL}/oauth-shoprenter-init?shopname=${shopname}&phoneNumberId=${phoneNumberId}`, {
|
|
|
- method: 'GET',
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${session.session.access_token}`,
|
|
|
- 'Content-Type': 'application/json'
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- if (!response.ok) {
|
|
|
- const errorData = await response.json();
|
|
|
- throw new Error(errorData.error || 'Failed to initiate OAuth flow');
|
|
|
- }
|
|
|
-
|
|
|
- const data = await response.json();
|
|
|
-
|
|
|
- if (data.success && data.installUrl) {
|
|
|
- // Redirect to ShopRenter admin to install the app
|
|
|
- setSuccess(true);
|
|
|
- setTimeout(() => {
|
|
|
- window.location.href = data.installUrl;
|
|
|
- }, 1000);
|
|
|
- } else {
|
|
|
- throw new Error('Invalid response from server');
|
|
|
- }
|
|
|
-
|
|
|
- } catch (err) {
|
|
|
- console.error("Connection error:", err);
|
|
|
- setError(err instanceof Error ? err.message : "Failed to connect to ShopRenter. Please try again.");
|
|
|
- setIsConnecting(false);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const handleKeyPress = (e: React.KeyboardEvent) => {
|
|
|
- if (e.key === "Enter" && !isConnecting) {
|
|
|
- handleConnect();
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
return (
|
|
|
<Card className="bg-slate-800 border-slate-700 max-w-2xl mx-auto shadow-none border-0">
|
|
|
<CardHeader>
|
|
|
@@ -115,100 +21,46 @@ export function ShopRenterConnect({ onClose }: ShopRenterConnectProps) {
|
|
|
</div>
|
|
|
</CardHeader>
|
|
|
<CardContent className="space-y-6">
|
|
|
- {/* Success Message */}
|
|
|
- {success && (
|
|
|
- <Alert className="bg-green-500/10 border-green-500/50">
|
|
|
- <CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
|
- <AlertDescription className="text-green-500">
|
|
|
- Successfully connected to ShopRenter! Redirecting to setup...
|
|
|
- </AlertDescription>
|
|
|
- </Alert>
|
|
|
- )}
|
|
|
-
|
|
|
- {/* Error Message */}
|
|
|
- {error && (
|
|
|
- <Alert className="bg-red-500/10 border-red-500/50">
|
|
|
- <AlertDescription className="text-red-500">
|
|
|
- {error}
|
|
|
- </AlertDescription>
|
|
|
- </Alert>
|
|
|
- )}
|
|
|
-
|
|
|
- {/* Connection Form */}
|
|
|
- <div className="space-y-4">
|
|
|
- <div className="space-y-2">
|
|
|
- <Label htmlFor="shopUrl" className="text-white">
|
|
|
- ShopRenter Shop URL
|
|
|
- </Label>
|
|
|
- <Input
|
|
|
- id="shopUrl"
|
|
|
- type="text"
|
|
|
- placeholder="yourshop.shoprenter.hu"
|
|
|
- value={shopUrl}
|
|
|
- onChange={(e) => setShopUrl(e.target.value)}
|
|
|
- onKeyPress={handleKeyPress}
|
|
|
- className="bg-slate-700 border-slate-600 text-white placeholder:text-slate-400"
|
|
|
- disabled={isConnecting}
|
|
|
- />
|
|
|
- <p className="text-sm text-slate-400">
|
|
|
- Enter your ShopRenter shop URL (e.g., mystore.shoprenter.hu)
|
|
|
- </p>
|
|
|
- </div>
|
|
|
-
|
|
|
- {/* Phone Number Selection */}
|
|
|
- <div className="space-y-2">
|
|
|
- <Label className="text-white">Select Phone Number *</Label>
|
|
|
- <PhoneNumberSelector
|
|
|
- value={phoneNumberId}
|
|
|
- onChange={setPhoneNumberId}
|
|
|
- disabled={isConnecting}
|
|
|
- />
|
|
|
- <p className="text-sm text-slate-400">
|
|
|
- This phone number will be permanently assigned to your store
|
|
|
- </p>
|
|
|
+ {/* Information about connecting via ShopRenter Admin */}
|
|
|
+ <div className="bg-cyan-500/10 border border-cyan-500/30 rounded-lg p-4 space-y-3">
|
|
|
+ <div className="flex items-start gap-3">
|
|
|
+ <Info className="w-5 h-5 text-cyan-500 mt-0.5 flex-shrink-0" />
|
|
|
+ <div className="space-y-2">
|
|
|
+ <h4 className="text-white font-medium">Install from ShopRenter App Store</h4>
|
|
|
+ <p className="text-sm text-slate-300">
|
|
|
+ ShopRenter stores can only be connected through the ShopRenter admin panel.
|
|
|
+ Please install our application from the ShopRenter App Store to connect your store.
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
-
|
|
|
- <Button
|
|
|
- onClick={handleConnect}
|
|
|
- disabled={isConnecting || !phoneNumberId}
|
|
|
- className="w-full bg-cyan-500 hover:bg-cyan-600 text-white"
|
|
|
- >
|
|
|
- {isConnecting ? (
|
|
|
- <>
|
|
|
- <Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
|
- Connecting...
|
|
|
- </>
|
|
|
- ) : (
|
|
|
- <>
|
|
|
- <Store className="w-4 h-4 mr-2" />
|
|
|
- Connect to ShopRenter
|
|
|
- </>
|
|
|
- )}
|
|
|
- </Button>
|
|
|
</div>
|
|
|
|
|
|
- {/* Information Section */}
|
|
|
+ {/* How to Connect Steps */}
|
|
|
<div className="bg-slate-700/50 rounded-lg p-4 space-y-3">
|
|
|
<h4 className="text-white font-medium flex items-center gap-2">
|
|
|
<ExternalLink className="w-4 h-4 text-cyan-500" />
|
|
|
- What happens next?
|
|
|
+ How to connect your store
|
|
|
</h4>
|
|
|
<ul className="space-y-2 text-sm text-slate-300">
|
|
|
<li className="flex items-start gap-2">
|
|
|
<span className="text-cyan-500 mt-0.5">1.</span>
|
|
|
- <span>You'll be redirected to ShopRenter to authorize the connection</span>
|
|
|
+ <span>Log in to your ShopRenter admin panel</span>
|
|
|
</li>
|
|
|
<li className="flex items-start gap-2">
|
|
|
<span className="text-cyan-500 mt-0.5">2.</span>
|
|
|
- <span>Grant the necessary permissions for AI caller integration</span>
|
|
|
+ <span>Navigate to the App Store section</span>
|
|
|
</li>
|
|
|
<li className="flex items-start gap-2">
|
|
|
<span className="text-cyan-500 mt-0.5">3.</span>
|
|
|
- <span>Return to ShopCall.ai to complete your AI assistant setup</span>
|
|
|
+ <span>Search for "ShopCall.ai" and click Install</span>
|
|
|
</li>
|
|
|
<li className="flex items-start gap-2">
|
|
|
<span className="text-cyan-500 mt-0.5">4.</span>
|
|
|
- <span>Start receiving AI-powered customer calls immediately</span>
|
|
|
+ <span>Grant the necessary permissions for AI caller integration</span>
|
|
|
+ </li>
|
|
|
+ <li className="flex items-start gap-2">
|
|
|
+ <span className="text-cyan-500 mt-0.5">5.</span>
|
|
|
+ <span>You'll be redirected back to ShopCall.ai to complete the setup</span>
|
|
|
</li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
@@ -247,15 +99,24 @@ export function ShopRenterConnect({ onClose }: ShopRenterConnectProps) {
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
- {/* Cancel Button */}
|
|
|
+ {/* App Store Link Placeholder - to be updated with actual link */}
|
|
|
+ {/* TODO: Add link to ShopRenter App Store when available */}
|
|
|
+ {/* <Button
|
|
|
+ className="w-full bg-cyan-500 hover:bg-cyan-600 text-white"
|
|
|
+ onClick={() => window.open('https://app-store-link', '_blank')}
|
|
|
+ >
|
|
|
+ <ExternalLink className="w-4 h-4 mr-2" />
|
|
|
+ Go to ShopRenter App Store
|
|
|
+ </Button> */}
|
|
|
+
|
|
|
+ {/* Close Button */}
|
|
|
{onClose && (
|
|
|
<Button
|
|
|
variant="outline"
|
|
|
onClick={onClose}
|
|
|
className="w-full border-slate-600 text-slate-300 hover:bg-slate-700"
|
|
|
- disabled={isConnecting}
|
|
|
>
|
|
|
- Cancel
|
|
|
+ Close
|
|
|
</Button>
|
|
|
)}
|
|
|
</CardContent>
|