feat: Implement OAuth license activation flow

- Add LicenseConnect.tsx focused OAuth confirmation page in customer SPA
- Add /licenses/oauth/validate and /licenses/oauth/confirm API endpoints
- Update App.tsx to render license-connect outside BaseLayout (no header/footer)
- Add license_activation_method field to product settings in Admin SPA
- Create LICENSING_MODULE.md with comprehensive OAuth flow documentation
- Update API_ROUTES.md with license module endpoints
This commit is contained in:
Dwindi Ramadhana
2026-01-31 22:22:22 +07:00
parent d80f34c8b9
commit a0b5f8496d
23 changed files with 3218 additions and 806 deletions

View File

@@ -80,49 +80,60 @@ function AppRoutes() {
const frontPageSlug = getFrontPageSlug();
return (
<BaseLayout>
<Routes>
{/* Root route: If frontPageSlug exists, render it. Else redirect to initialRoute (e.g. /shop) */}
<Route
path="/"
element={
frontPageSlug ? (
<DynamicPageRenderer slug={frontPageSlug} />
) : (
<Navigate to={initialRoute === '/' ? '/shop' : initialRoute} replace />
)
}
/>
<Routes>
{/* License Connect - Standalone focused page without layout */}
<Route path="/my-account/license-connect" element={<Account />} />
{/* Shop Routes */}
<Route path="/shop" element={<Shop />} />
<Route path="/product/:slug" element={<Product />} />
{/* All other routes wrapped in BaseLayout */}
<Route
path="/*"
element={
<BaseLayout>
<Routes>
{/* Root route: If frontPageSlug exists, render it. Else redirect to initialRoute (e.g. /shop) */}
<Route
path="/"
element={
frontPageSlug ? (
<DynamicPageRenderer slug={frontPageSlug} />
) : (
<Navigate to={initialRoute === '/' ? '/shop' : initialRoute} replace />
)
}
/>
{/* Cart & Checkout */}
<Route path="/cart" element={<Cart />} />
<Route path="/checkout" element={<Checkout />} />
<Route path="/order-received/:orderId" element={<ThankYou />} />
<Route path="/checkout/order-received/:orderId" element={<ThankYou />} />
<Route path="/checkout/pay/:orderId" element={<OrderPay />} />
{/* Shop Routes */}
<Route path="/shop" element={<Shop />} />
<Route path="/product/:slug" element={<Product />} />
{/* Wishlist - Public route accessible to guests */}
<Route path="/wishlist" element={<Wishlist />} />
{/* Cart & Checkout */}
<Route path="/cart" element={<Cart />} />
<Route path="/checkout" element={<Checkout />} />
<Route path="/order-received/:orderId" element={<ThankYou />} />
<Route path="/checkout/order-received/:orderId" element={<ThankYou />} />
<Route path="/checkout/pay/:orderId" element={<OrderPay />} />
{/* Login & Auth */}
<Route path="/login" element={<Login />} />
<Route path="/forgot-password" element={<ForgotPassword />} />
<Route path="/reset-password" element={<ResetPassword />} />
{/* Wishlist - Public route accessible to guests */}
<Route path="/wishlist" element={<Wishlist />} />
{/* My Account */}
<Route path="/my-account/*" element={<Account />} />
{/* Login & Auth */}
<Route path="/login" element={<Login />} />
<Route path="/forgot-password" element={<ForgotPassword />} />
<Route path="/reset-password" element={<ResetPassword />} />
{/* Dynamic Pages - CPT content with path base (e.g., /blog/:slug) */}
<Route path="/:pathBase/:slug" element={<DynamicPageRenderer />} />
{/* My Account */}
<Route path="/my-account/*" element={<Account />} />
{/* Dynamic Pages - Structural pages (e.g., /about, /contact) */}
<Route path="/:slug" element={<DynamicPageRenderer />} />
</Routes>
</BaseLayout>
{/* Dynamic Pages - CPT content with path base (e.g., /blog/:slug) */}
<Route path="/:pathBase/:slug" element={<DynamicPageRenderer />} />
{/* Dynamic Pages - Structural pages (e.g., /about, /contact) */}
<Route path="/:slug" element={<DynamicPageRenderer />} />
</Routes>
</BaseLayout>
}
/>
</Routes>
);
}