In this part, we'll integrate the finance dashboard we bootstrapped and the improved analyzer model into our application. Specifically, we will integrate the WebSocket-backed server with our SvelteKit frontend.

It's assumed you have completed the previous parts of this series.

Sirneij
Sirneij/finance-analyzer
00

An AI-powered financial behavior analyzer and advisor written in Python (aiohttp) and TypeScript (ExpressJS & SvelteKit with Svelte 5)

sveltetypescriptpythonjavascriptcss3html5

To kick things off, we'll create a reusable WebSocket service. This service will handle the communication between our SvelteKit frontend and the backend server:

src/lib/services/websocket.ts
typescript

As mentioned earlier, we currently support two primary operations: analyze and summary. This WebSocket service abstracts the underlying complexities of `WebSocket` communication, providing a clean and manageable interface for our SvelteKit components. We'll be focusing on modifying the onMessage method within these components to handle incoming data effectively.

Let's see how the service is used in a component:

src/routes/finanalyzer/(dashboard)/+page.svelte
html

We have a couple of SvelteKit-specific concepts to clarify. First, notice the (dashboard) directory within the routes folder. This is a Route Group in SvelteKit. SvelteKit uses file-system routing, where +page.svelte files define your application's routes. As SvelteKit's documentation states:

By default, the layout hierarchy mirrors the route hierarchy.

Route groups allow you to organize your routes without affecting the URL structure. This is useful when you want a subset of your application to share a layout without including the group's name in the URL.

In this group, there is a layout:

src/routes/finanalyzer/(dashboard)/+layout.svelte
html

This code implements the main dashboard layout, building upon the concepts discussed in the finance dashboard article. The layout includes a responsive sidebar, a header with a theme switcher, and a main content area. The other components used in this layout can be found in the series repository.

Back in +page.svelte, the WebSocket service is initialized using Svelte's onMount lifecycle hook. This ensures that the service is started after the component has been mounted in the DOM. Immediately after initialization, requests for analysis and summaries are sent to the server. The component also subscribes to progress updates to keep the user informed about the status of their requests. The received data is then dispatched to other Svelte components for rendering (we will only zoom in on one here for brevity. Others can be seen in the repo.).

Let's delve into the FinanceChart component, which leverages ApexChartsJS to provide a visually appealing representation of the user's spending analysis. This component offers a fullscreen mode for enhanced interaction and data exploration.

src/lib/components/transactions/FinanceChart.svelte
html

Since we are exclusively building our app with Svelte 5 runes, this component retrieves the spending analysis data from the $props() and then defines some states. The initChart function handles the chart plotting. It's crucial to check for the browser environment and the presence of the chart element in the DOM to prevent errors like apexcharts.common.js:... Uncaught (in promise) Error: Element not found. Dynamic import for ApexCharts is used instead of direct import at the top of the file to further mitigate these issues. The base configurations for all charts are defined in src/lib/utils/helpers/charts.helpers.ts:

src/lib/utils/helpers/charts.helpers.ts
typescript

These configurations define basic options for all charts and specific settings for financial charts.

With that, we'll stop here for this part. See you in the next one!

Enjoyed this article? I'm a Software Engineer, Technical Writer and Technical Support Engineer actively seeking new opportunities, particularly in areas related to web security, finance, healthcare, and education. If you think my expertise aligns with your team's needs, let's chat! You can find me on LinkedIn and X. I am also an email away.

If you found this article valuable, consider sharing it with your network to help spread the knowledge!