diff --git a/src/lib/IONOS/components/ai-team/AgentCard.svelte b/src/lib/IONOS/components/ai-team/AgentCard.svelte new file mode 100644 index 00000000000..351c9f685c8 --- /dev/null +++ b/src/lib/IONOS/components/ai-team/AgentCard.svelte @@ -0,0 +1,93 @@ + + +
e.key === 'Enter' && handleCardClick()} + role="button" + tabindex="0" +> +
+ {#if agent.id} + Model Avatar + {:else} +
+ {agent.name.charAt(0)} +
+ {/if} +
+

+ {agent.name} +

+ {#if agent.speciality} +

+ {agent.speciality} +

+ {/if} +
+ +
+ +

+ {agent.description} +

+
+ + + +
+ +
+
\ No newline at end of file diff --git a/src/lib/IONOS/components/ai-team/AgentCardDetail.svelte b/src/lib/IONOS/components/ai-team/AgentCardDetail.svelte new file mode 100644 index 00000000000..cf48d3c5d07 --- /dev/null +++ b/src/lib/IONOS/components/ai-team/AgentCardDetail.svelte @@ -0,0 +1,103 @@ + + +
+
+ +
+
+ {#if agent.id} + {agent.name} + {:else} +
+ {agent.name.charAt(0)} +
+ {/if} + +
+

+ {agent.name} +

+ {#if agent.speciality} +

+ {agent.speciality} +

+ {/if} +
+
+ +
+

+ {agent.description} +

+
+ + + {#if agent.capabilities && agent.capabilities.length > 0} +
+

+ Capabilities +

+
+ {#each agent.capabilities as capability} +
+ + {capability} +
+ {/each} +
+
+ {/if} + +
+ +
+
\ No newline at end of file diff --git a/src/lib/IONOS/components/ai-team/ai-team.type.ts b/src/lib/IONOS/components/ai-team/ai-team.type.ts new file mode 100644 index 00000000000..dfec96c4597 --- /dev/null +++ b/src/lib/IONOS/components/ai-team/ai-team.type.ts @@ -0,0 +1,10 @@ + export interface IAgentAiTeam { + id: string; + name: string; + speciality: string; + description: string; + capabilities?: string[]; + externalLink?: string; + showCrown?: boolean; + highlight?: boolean; + } \ No newline at end of file diff --git a/src/lib/IONOS/components/explore/LoginRegisterOverlay.svelte b/src/lib/IONOS/components/explore/LoginRegisterOverlay.svelte deleted file mode 100644 index cd835b9393c..00000000000 --- a/src/lib/IONOS/components/explore/LoginRegisterOverlay.svelte +++ /dev/null @@ -1,76 +0,0 @@ - - - dispatch('close')} -> -
-

- {$i18n.t('Your AI Experts Are Ready', { ns: 'ionos' })} -

- -
- - - - -
-

- {$i18n.t('Customer ID, email address or domain', { ns: 'ionos' })} -

- - -
- -
-

- {$i18n.t('Not an IONOS customer yet?', { ns: 'ionos' })} -

- - dispatch('signup')} - className="inline-block mt-3 text-sm text-blue-700" - > - {$i18n.t('Sign up now for FREE to start creating with AI', { ns: 'ionos' })} - -
-
-
diff --git a/src/lib/IONOS/components/icons/Crown.svelte b/src/lib/IONOS/components/icons/Crown.svelte new file mode 100644 index 00000000000..3a017271b09 --- /dev/null +++ b/src/lib/IONOS/components/icons/Crown.svelte @@ -0,0 +1,13 @@ + + + + + + + diff --git a/src/lib/IONOS/components/icons/IonosLogo.svelte b/src/lib/IONOS/components/icons/IonosLogo.svelte index ffa92a20c2f..3090f18b352 100644 --- a/src/lib/IONOS/components/icons/IonosLogo.svelte +++ b/src/lib/IONOS/components/icons/IonosLogo.svelte @@ -8,8 +8,62 @@ Origin: Figma --> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/IONOS/services/signup.spec.ts b/src/lib/IONOS/services/signup.spec.ts deleted file mode 100644 index 00b7b2b303a..00000000000 --- a/src/lib/IONOS/services/signup.spec.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { describe, beforeEach, expect, it, vi } from 'vitest'; -import { - LOCALSTORAGE_REFERRED_TO_SIGNUP, - signup, - handleSignupDone, -} from './signup'; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Config = Record; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type User = any; -type ConfigSubscriber = (config: Config) => void -type UserSubscriber = (user: User) => void - -const mocks = vi.hoisted(() => { - return { - stores: { - config: { - subscribe: vi.fn(), - }, - user: { - subscribe: vi.fn(), - }, - }, - navigation: { - goto: vi.fn(), - }, - }; -}); - -vi.mock('$lib/stores', async () => { - return { - config: mocks.stores.config, - user: mocks.stores.user, - }; -}); - -vi.mock('$app/navigation', async () => { - return { - goto: mocks.navigation.goto, - }; -}); - -vi.stubGlobal('window', { - location: { href: 'unset' }, -}); - -vi.stubGlobal('localStorage', { - getItem: vi.fn(), - setItem: vi.fn(), - removeItem: vi.fn(), -}); - -describe('signup', () => { - function mockConfig(config: Config) { - mocks.stores.config.subscribe.mockImplementation((subscriber: ConfigSubscriber) => { - subscriber(config); - return () => { }; - }); - } - - function mockUser(user: User|undefined) { - mocks.stores.user.subscribe.mockImplementation((subscriber: UserSubscriber) => { - subscriber(user); - return () => { }; - }); - } - - function mockLocalStoage(key: string, value: string|null) { - vi.mocked(localStorage.getItem).mockImplementation((requestedKey: string) => { - if (requestedKey === key) { - return value; - } - return null; - }); - } - - const mockRegistrationUrl = 'http://registration/'; - - beforeEach(() => { - vi.resetAllMocks(); - window.location.href = 'unset'; - }); - - describe('signup()', () => { - it('should set a marker in localStorage then rediect to the configured signup URL if configured', () => { - mockConfig({ - features: { - ionos_registration_url: mockRegistrationUrl, - }, - }); - - signup(); - - expect(localStorage.setItem).toHaveBeenCalledWith(LOCALSTORAGE_REFERRED_TO_SIGNUP, 'true'); - expect(window.location.href).toBe(mockRegistrationUrl); - }); - - it('should set a marker in localStorage and not redirect if no signup URL is configured', () => { - mockConfig({ - features: { - ionos_registration_url: null, - }, - }); - - signup(); - - expect(localStorage.setItem).toHaveBeenCalledWith(LOCALSTORAGE_REFERRED_TO_SIGNUP, 'true'); - expect(window.location.href).toBe('unset'); - }); - }); - - describe('handleSignupDone()', () => { - describe('user is authenticated and went through signup', () => { - beforeEach(() => { - mockLocalStoage(LOCALSTORAGE_REFERRED_TO_SIGNUP, 'true'); - mockUser({ /* mock user */ }); - handleSignupDone(); - }); - - it('should redirect', () => { - expect(mocks.navigation.goto).toHaveBeenCalledWith('/explore'); - }); - - it('should remove an item from localStorage', () => { - expect(localStorage.removeItem).toHaveBeenCalledWith(LOCALSTORAGE_REFERRED_TO_SIGNUP); - }); - }); - - describe('user is authenticated and did not go through signup', () => { - beforeEach(() => { - mockLocalStoage(LOCALSTORAGE_REFERRED_TO_SIGNUP, 'false'); - mockUser({ /* mock user */ }); - handleSignupDone(); - }); - - it('should not redirect', () => { - expect(mocks.navigation.goto).not.toHaveBeenCalled(); - }); - - it('should not remove an item from localStorage', () => { - expect(localStorage.removeItem).not.toHaveBeenCalledWith(LOCALSTORAGE_REFERRED_TO_SIGNUP); - }); - }); - - describe('user is not authenticated and went through signup', () => { - beforeEach(() => { - mockLocalStoage(LOCALSTORAGE_REFERRED_TO_SIGNUP, 'true'); - mockUser(undefined); - handleSignupDone(); - }); - - it('should not redirect', () => { - expect(mocks.navigation.goto).not.toHaveBeenCalled(); - }); - - it('should not remove an item from localStorage', () => { - expect(localStorage.removeItem).not.toHaveBeenCalledWith(LOCALSTORAGE_REFERRED_TO_SIGNUP); - }); - }); - - describe('user is not authenticated and did not go through signup', () => { - beforeEach(() => { - mockLocalStoage(LOCALSTORAGE_REFERRED_TO_SIGNUP, 'false'); - mockUser(undefined); - handleSignupDone(); - }); - - it('should not redirect', () => { - expect(mocks.navigation.goto).not.toHaveBeenCalled(); - }); - - it('should not remove an item from localStorage', () => { - expect(localStorage.removeItem).not.toHaveBeenCalledWith(LOCALSTORAGE_REFERRED_TO_SIGNUP); - }); - }); - }); -}); diff --git a/src/lib/IONOS/services/signup.ts b/src/lib/IONOS/services/signup.ts deleted file mode 100644 index 949570060e4..00000000000 --- a/src/lib/IONOS/services/signup.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { get } from 'svelte/store'; -import { config, user } from '$lib/stores'; -import { goto } from '$app/navigation'; - -export const LOCALSTORAGE_REFERRED_TO_SIGNUP = 'ionosgptUserReferredToSignup'; - -export const signup = (): void => { - localStorage.setItem(LOCALSTORAGE_REFERRED_TO_SIGNUP, JSON.stringify(true)); - - const url: string|null = get(config)?.features?.ionos_registration_url ?? null; - - if (url) { - window.location.href = url; - } -} - -export const handleSignupDone = async (): Promise => { - const userIsAuthenticated = !!get(user); - const userWentThroughSignup: boolean = JSON.parse(localStorage.getItem(LOCALSTORAGE_REFERRED_TO_SIGNUP) ?? 'false'); - - if (userWentThroughSignup && userIsAuthenticated) { - console.log('User went through signup, sending them to the explore page ...'); - - localStorage.removeItem(LOCALSTORAGE_REFERRED_TO_SIGNUP); - - await goto('/explore'); - } else if (!userIsAuthenticated) { - console.log('User went through signup, but is not authenticated. '); - } -} diff --git a/src/lib/components/layout/Sidebar.svelte b/src/lib/components/layout/Sidebar.svelte index 1369c4347fe..168d06a761d 100644 --- a/src/lib/components/layout/Sidebar.svelte +++ b/src/lib/components/layout/Sidebar.svelte @@ -542,7 +542,7 @@ {#if $showSidebar}
- {$i18n.t('Explore', { ns: 'ionos' })} + {$i18n.t('ai.team.nav', { ns: 'ionos' })}
{/if} diff --git a/src/lib/components/layout/Sidebar/UserMenu.svelte b/src/lib/components/layout/Sidebar/UserMenu.svelte index d05f3c793f4..292d7758632 100644 --- a/src/lib/components/layout/Sidebar/UserMenu.svelte +++ b/src/lib/components/layout/Sidebar/UserMenu.svelte @@ -42,26 +42,25 @@ align="start" transition={(e) => fade(e, { duration: 100 })} > - {#if page.url.pathname !== '/explore'} - - {/if} + - {#if page.url.pathname !== '/explore' && !$mobile} + {#if !$mobile}