Thursday, November 14, 2024
HomeC#AI-Powered Sensible .NET MAUI Scheduler for Straightforward Appointment Reserving

AI-Powered Sensible .NET MAUI Scheduler for Straightforward Appointment Reserving


TL;DR: Let’s construct an AI-powered sensible scheduler in .NET MAUI for seamless appointment reserving and availability checks. This weblog covers integrating Azure OpenAI, designing a chatbot, and configuring the .NET MAUI Scheduler to handle appointments effectively. We’ll additionally exhibit use the AI AssistView management to automate scheduling duties. 

Syncfusion .NET MAUI Scheduler (SfScheduler) has 9 built-in configurable view modes that present fundamental performance for scheduling, managing, and representing appointments effectively. It has been redesigned with a clear and handy consumer interface for customized working days and hours and fundamental calendar operations comparable to date navigation and choice.

The AI-powered sensible Scheduler simplifies appointment reserving by means of AI service. It robotically suggests useful resource availability and schedules with out direct interplay with the .NET MAUI Scheduler utilizing Azure OpenAI.

On this weblog, we’ll exhibit design a Chatbot with the .NET MAUI Scheduler for sensible appointment scheduling and checking medical doctors’ availability utilizing Azure OpenAI. On the similar time, the consumer enters a immediate or enter within the .NET MAUI AI AssistView (SfAIAssistView) and guide the appointment utilizing the .NET MAUI Scheduler.

Let’s get began!

Integrating Azure OpenAI with the .NET MAUI app

First, open Visible Studio and create a brand new .NET MAUI app.

Earlier than integrating the ability of the AI AssistView function, guarantee that you’ve got entry to Azure OpenAI and have arrange a deployment within the Azure portal. You’ll find the Azure.AI.OpenAI NuGet package deal within the NuGet Gallery and set up it within the pattern.

When you get your key and endpoint and configure Azure OpenAI, we’ll assume you’ll use the GPT-35 mannequin deployed underneath the title GPT35Turbo. Let’s begin by creating the OpenAIService, as proven within the following code instance.

inside class AzureOpenAIService
{
    const string endpoint = "https://{YOUR_END_POINT}.openai.azure.com";
    const string deploymentName = "GPT35Turbo";
    string key = "API key";

    OpenAIClient? shopper;
    ChatCompletionsOptions? chatCompletions;

    inside AzureOpenAIService()
    {
    }
}

Hook up with the Azure OpenAI

Within the .NET MAUI app, arrange a connection to the Azure OpenAI service, as proven within the following code instance.

// On the time of required.
this.shopper = new OpenAIClient(new Uri(endpoint), new AzureKeyCredential(key));

This connection means that you can ship prompts to the AI service and obtain responses.

Implement a way to ship a immediate to OpenAI

Now, implement the GetResponseFromGPT methodology to ship a immediate to the OpenAI API and retrieve the completion consequence.

inside class AzureOpenAIService
{
    const string endpoint = "https://{YOUR_END_POINT}.openai.azure.com";
    const string deploymentName = "GPT35Turbo";
    string key = "API key";
    
    OpenAIClient? shopper;
    ChatCompletionsOptions? chatCompletions;
    
    inside AzureOpenAIService()
    {
        
    }
    
    inside async Process<string> GetResponseFromGPT(string userPrompt)
    {
        this.chatCompletions = new ChatCompletionsOptions
        {
            DeploymentName = deploymentName,
            Temperature = (float)0.5f,
            MaxTokens = 800,
            NucleusSamplingFactor = (float)0.95f,
            FrequencyPenalty = 0,
            PresencePenalty = 0,
        };
        
        this.shopper = new OpenAIClient(new Uri(endpoint), new AzureKeyCredential(key));
        if (this.shopper != null)
        {
            // Add the consumer's immediate as a consumer message to the dialog.
            this.chatCompletions?.Messages.Add(new ChatRequestSystemMessage("You're a predictive analytics assistant."));
            
            // Add the consumer's immediate as a consumer message to the dialog.
            this.chatCompletions?.Messages.Add(new ChatRequestUserMessage(userPrompt));
            strive
            {
                // Ship the chat completion request to the OpenAI API and await the response.
                var response = await this.shopper.GetChatCompletionsAsync(this.chatCompletions);
                
                // Return the content material of the primary selection within the response, which accommodates the AI's reply.
                return response.Worth.Selections[0].Message.Content material;
            }
            catch
            {
                // If an exception happens (e.g., community points, API errors), return an empty string.
                return "";
            }
        }
        return "";
    }
}

That’s it! The AzureOpenAIService class will now present a handy option to work together with the OpenAI API and retrieve completion outcomes primarily based on the immediate given within the SfAIAssistView management.

Designing the AI-powered sensible .NET MAUI Scheduler for medical doctors

We will add a number of medical doctors and group appointments primarily based on them in a single calendar, simplifying group with no need a number of calendars. The .NET MAUI Scheduler means that you can handle sources in timeline views. Earlier than continuing, please consult with the getting began with the .NET MAUI Scheduler documentation.

Step 1: Create a scheduler useful resource mannequin

Outline a useful resource or physician mannequin with the next fields: Title, Id, Background, Foreground and ImageName.

ResourceViewModel.cs

public class ResourceViewModel
{
    public string Title { get; set; }
    public string? Id { get; set; }
    public Brush Background { get; set; }
    public Brush Foreground { get; set; }
    public string ImageName { get; set; }
}

Step 2: Create sources for the scheduler

Within the ViewModel class, create the useful resource or physician assortment certain to the .NET MAUI Scheduler.

SchedulerViewModel.cs

  
public class SchedulerViewModel
{
  public ObservableCollection<object>? Sources { get; set; } 
  public SchedulerViewModel()
  {
      
      InitializeResources();
  }
  /// <abstract>
  /// Technique to initialize the sources.
  /// </abstract>
  non-public void InitializeResources()
  {
     this.Sources = new ObservableCollection<object>();
     for (int i = 0; i < 2; i++)
     {
         ResourceViewModel resourceViewModel = new ResourceViewModel();
         if (i == 0)
         {
             resourceViewModel.Title = "Sophia";
             resourceViewModel.ImageName = "people_circle1.png";
             resourceViewModel.Id = "1000";
             resourceViewModel.Background = new SolidColorBrush(Shade.FromArgb("#36B37B"));
         }
         else 
         {
             resourceViewModel.Title = "John";
             resourceViewModel.ImageName = "people_circle8.png";
             resourceViewModel.Id = "1001";
             resourceViewModel.Background = new SolidColorBrush(Shade.FromArgb("#8B1FA9"));
         }
          
         Sources?.Add(resourceViewModel);
     }
  }
}

Step 3: Create the Scheduler for medical doctors

Then, create the Timeline Day Scheduler view and bind the sources from the ViewModel class to the SchedulerResourceView class’s Sources property. Then, map the customized ResourceViewModel properties to the Mapping properties of the SchedulerResourceView class.

Additionally, customise the useful resource header template to enhance visualization.

xmlns:scheduler="clr-namespace:Syncfusion.Maui.Scheduler;meeting=Syncfusion.Maui.Scheduler"

<Grid.BindingContext>
  <native:SchedulerViewModel />
</Grid.BindingContext>

<scheduler:SfScheduler x:Title="scheduler" View="TimelineDay"> 
  <scheduler:SfScheduler.TimelineView>
    <scheduler:SchedulerTimelineView StartHour="9" 
                                     TimeInterval="0:30:0" 
                                     TimeIntervalWidth="90" 
                                     TimeFormat="hh:mm" 
                                     EndHour="18" />
  </scheduler:SfScheduler.TimelineView>
  
  <scheduler:SfScheduler.ResourceView>
    <scheduler:SchedulerResourceView Sources="{Binding Sources}">
      <scheduler:SchedulerResourceView.Mapping>
        <scheduler:SchedulerResourceMapping Title="Title"
                                            Id="Id"
                                            Background="Background"
                                            Foreground="Foreground" />
      </scheduler:SchedulerResourceView.Mapping>

      <scheduler:SchedulerResourceView.HeaderTemplate>
        <DataTemplate>
          <StackLayout Padding="5"
                       Orientation="Vertical"
                       VerticalOptions="Heart"
                       HorizontalOptions="Fill">
            <Grid>
              <Border StrokeThickness="2"
                      Background="{Binding Background}"
                      HorizontalOptions="Heart"
                      HeightRequest="{OnPlatform WinUI=70, MacCatalyst=70, Android=65, iOS=65}"
                      WidthRequest="{OnPlatform WinUI=70, MacCatalyst=70, Android=65, iOS=65}">
                <Border.StrokeShape>
                  <RoundRectangle CornerRadius="150" />
                </Border.StrokeShape>
              </Border>

              <Picture WidthRequest="{OnPlatform WinUI=55, MacCatalyst=55, Android=50, iOS=50}"
                     HeightRequest="{OnPlatform WinUI=55, MacCatalyst=55, Android=50, iOS=50}"
                     HorizontalOptions="Heart"
                     VerticalOptions="Heart"
                     Supply="{Binding DataItem.ImageName, Converter={StaticResource imageConverter}}"
                     Facet="Fill" />
            </Grid>

            <Label Textual content="{Binding Title}"
                   FontSize="{OnPlatform WinUI=12, MacCatalyst=12, Android=10, iOS=10}"
                   VerticalTextAlignment="Heart"
                   HorizontalTextAlignment="Heart" />
          </StackLayout>
        </DataTemplate>
      </scheduler:SchedulerResourceView.HeaderTemplate>
    </scheduler:SchedulerResourceView>
  </scheduler:SfScheduler.ResourceView>
</scheduler:SfScheduler>

Check with the next picture.

.NET MAUI Scheduler resource view
.NET MAUI Scheduler useful resource view

Step 4: Design an AI assistant chat view

Now, create an AI assistant chat view through which the consumer enters a immediate or enter utilizing the .NET MAUI SfAIAssistView to test the physician’s availability and use Chatbot with Scheduler.

xmlns:aiassistview="clr-namespace:Syncfusion.Maui.AIAssistView;meeting=Syncfusion.Maui.AIAssistView"

<Grid.BindingContext>
 <native:SchedulerViewModel />
</Grid.BindingContext>

<aiassistview:SfAIAssistView Grid.Column="{OnPlatform Android='0',iOS='0', Default="1"}"
                             Margin="0,100,0,0"
                             IsVisible="{Binding ShowAssistView, Mode=TwoWay}"
                             HorizontalOptions="{OnPlatform Android=Fill, iOS=Fill, Default=Finish}"
                             MaximumWidthRequest="{OnPlatform WinUI=700}"
                             x:Title="aiAssistView"
                             ShowHeader="{Binding ShowHeader}"
                             AssistItems="{Binding Messages}">
 <aiassistview:SfAIAssistView.Shadow>
   <Shadow Brush="Black" Offset="0,0" Radius="1" Opacity="0.5" />
 </aiassistview:SfAIAssistView.Shadow>
</aiassistview:SfAIAssistView>

Check with the next picture.

Designing an AI assistant chat view
Designing an AI assistant chat view

Step 5: Test the physician’s availability utilizing AI service

When the consumer inputs texts into the SfAIAssistView chat, the immediate is shipped to the AI service, and the physician’s availability occasions are listed within the SfAIAssistView sensible element.

AssistViewBehavior.cs

this.assistView.Request += this.OnAssistViewRequest;

non-public async void OnAssistViewRequest(object? sender, RequestEventArgs e)
{
    if (azureAIServices.Consumer != null)
    {
        if (string.IsNullOrEmpty(e.RequestItem.Textual content))
        {
            return;
        }
        
        string sample = @"bd{2}:d{2} (AM|PM)b";
        bool isValidPattern = Regex.IsMatch(requeststring, sample);
        if (!isValidPattern)
        {
            await this.SchedulerViewModel.GetAIResults(e.RequestItem.Textual content).ConfigureAwait(true);
        }
    }
}

SchedulerViewModel.cs

///<abstract>
/// Technique to get the AI response.
///</abstract> 
///<param title="question">The question</param>
///<returns></returns> 
public async Process GetAIResults(string question)
{
    await Process.Delay(1000).ConfigureAwait(true);
    var reply = await this.GetRecommendation(question);
    AssistItem botMessage = new AssistItem() { Textual content = reply, ShowAssistItemFooter = false };
    this.Messages.Add(botMessage);
}

After the consumer enters the appointment reserving particulars, the AI service lists the physician’s availability, which is then parsed as a JObject object.

SchedulerViewModel.cs

///<abstract>
/// Technique to include AI response and updates.
///</abstract> 
///<param title="userInput">The consumer enter</param>
///<returns></returns> 
non-public async Process<string> GetRecommendation(string userInput)
{
    DateTime todayDate = DateTime.At this time;
    string immediate = $"Given knowledge: {userInput}. Based mostly on the given knowledge, present 10 appointment time particulars for Doctor1 and Doctor2 on {todayDate}." +
                    $"Availability time is 9AM to 6PM." +
                    $"In 10 appointments, cut up the time particulars as 5 for Doctor1 and 5 for Doctor2." +
                    $"Present full appointment time particulars for each Doctor1 and Doctor2 with out lacking any fields." +
                    $"It needs to be half-hour appointment length." +
                    $"Doctor1 time particulars mustn't collide with Doctor2." +
                    $"Present ResourceID for Doctor1 as 1000 and for Doctor2 as 1001." +
                    $"Don't repeat the identical time. Generate the next fields: StartDate, EndDate, Topic, Location, and ResourceID." +
                    $"The return format needs to be the next JSON format: Doctor1[StartDate, EndDate, Subject, Location, ResourceID], Doctor2[StartDate, EndDate, Subject, Location, ResourceID]." +
                    $"Situation: present particulars with none rationalization. Do not embody any particular characters like ```";
    
    returnMessage = await azureAIServices.GetResultsFromAI(immediate);
    var jsonObj = JObject.Parse(returnMessage);
    
    var doctorAppointments = new Dictionary<string, (Record<DateTime> StartTimes, Record<DateTime> EndTimes, Record<string> Topics, Record<string> Places, Record<string> ResourceIDs)>
    {
      { "Doctor1", (new Record<DateTime>(), new Record<DateTime>(), new Record<string>(), new Record<string>(), new Record<string<()) },
      { "Doctor2", (new Record<DateTime>(), new Record<DateTime>(), new Record<string>(), new Record<string>(), new Record<string>()) }
   };

   foreach (var physician in doctorAppointments.Keys)
    {
        foreach (var appointment in jsonObj[doctor])
        {
            if (DateTime.TryParse((string)appointment["StartDate"], out DateTime startTime) && DateTime.TryParse((string)appointment["EndDate"], out DateTime endTime))
            {
                doctorAppointments[doctor].StartTimes.Add(startTime);
                doctorAppointments[doctor].EndTimes.Add(endTime);
            }
            
            doctorAppointments[doctor].Topics.Add((string)appointment["Subject"]);            
            doctorAppointments[doctor].Places.Add((string)appointment["Location"]);            
            doctorAppointments[doctor].ResourceIDs.Add((string)appointment["ResourceID"]);
        }
    }
    this.SophiaStartTimeCollection = doctorAppointments["Doctor1"].StartTimes;
    this.SophiaEndTimeCollection = doctorAppointments["Doctor1"].EndTimes;
    this.SophiaSubjectCollection = doctorAppointments["Doctor1"].Topics;
    this.SophiaLocationCollection = doctorAppointments["Doctor1"].Places;
    this.SophiaResourceIDCollection = doctorAppointments["Doctor1"].ResourceIDs;
    this.JohnStartTimeCollection = doctorAppointments["Doctor2"].StartTimes;
    this.JohnEndTimeCollection = doctorAppointments["Doctor2"].EndTimes;
    this.JohnSubjectCollection = doctorAppointments["Doctor2"].Topics;
    this.JohnLocationCollection = doctorAppointments["Doctor2"].Places;
    this.JohnResourceIDCollection = doctorAppointments["Doctor2"].ResourceIDs;
    this.SophiaAvailableTimeSlots = GenerateTimeSlots(SophiaStartTimeCollection);
    this.JohnAvailableTimeSlots = GenerateTimeSlots(JohnStartTimeCollection);
    return GenerateFinalTimeSlots(userInput);
}
///<abstract>
/// Technique to generate the ultimate time slots.
///<abstract> 
///<param title="userInput">The consumer enter</param>
///<returns></returns> 
non-public string GenerateFinalTimeSlots(string userInput)
{
    string sophiaAvailedTimeSlots = string.Be a part of(" n ", this.SophiaAvailableTimeSlots);
    string johnAvailedTimeSlots = string.Be a part of(" n ", this.JohnAvailableTimeSlots);
    if (userInput.Accommodates("Sophia"))
    {
        return $"Physician Sophia obtainable appointment slots aren {sophiaAvailedTimeSlots} nEnter the time (hh:mm tt) to guide an appointment.";
    }
    else if (userInput.Accommodates("John"))
    {
        return $"Physician John obtainable appointment slots aren {johnAvailedTimeSlots} nEnter the time (hh:mm tt) to guide an appointment.";
    }
    else
    {
        return $"Physician Sophia obtainable appointment slots aren {sophiaAvailedTimeSlots}nDoctor John obtainable appointment slots aren {johnAvailedTimeSlots}nEnter the time (hh:mm tt) to guide an appointment.";
    }
}
////<abstract>
/// Retrieves a solution from the deployment title mannequin utilizing the supplied consumer immediate.
////</abstract> 
////<param title="userPrompt">The consumer immediate.</param>
////<returns>The AI response.<returns>
public async Process<string> GetResultsFromAI(string userPrompt)
{
    if (this.Consumer != null && this.chatCompletions != null)
    {
        // Add the system message and consumer message to the choices
        this.chatCompletions.Messages.Add(new ChatRequestSystemMessage("You're a predictive analytics assistant."));
        this.chatCompletions.Messages.Add(new ChatRequestUserMessage(userPrompt));
        strive
        {
            var response = await Consumer.GetChatCompletionsAsync(this.chatCompletions);
            return response.Worth.Selections[0].Message.Content material;
        }
        catch
        {
            return string.Empty;
        }
    }

    return string.Empty;
}

Step 6: E-book the appointment with a health care provider

As soon as the consumer enters the reserving time, primarily based on the physician’s availability listed from the AI service, reserving particulars are transformed to scheduler appointments and appointments with out interacting with the .NET MAUI Scheduler.

AssistViewBehavior.cs

non-public async void OnAssistViewRequest(object? sender, RequestEventArgs e)
{
    string requeststring = e.RequestItem.Textual content;
    DateTime sophiaStartTime;
    DateTime sophiaEndTime;
    string sophiaSubject = string.Empty;
    string sophiaLocation = string.Empty;
    string sophiaResourceID = string.Empty;
    DateTime johnStartTime;
    DateTime johnEndTime;
    string johnSubject = string.Empty;
    string johnLocation = string.Empty;
    string johnResourceID = string.Empty;
    
    if (azureAIServices.Consumer != null)
    {
        if (string.IsNullOrEmpty(e.RequestItem.Textual content))
        {
            return;
        }
        
        string sample = @"bd{2}:d{2} (AM|PM)b";
        bool isValidPattern = Regex.IsMatch(requeststring, sample);
        
        if (!isValidPattern)
        {
            await this.SchedulerViewModel.GetAIResults(e.RequestItem.Textual content).ConfigureAwait(true);
        }
        else
        {
            for (int i = 0; i < this.SchedulerViewModel.SophiaAvailableTimeSlots?.Rely; i++)
            {
                if (requeststring == this.SchedulerViewModel.SophiaAvailableTimeSlots[i].ToString())
                {
                    sophiaStartTime = this.SchedulerViewModel.SophiaStartTimeCollection[i];
                    sophiaEndTime = this.SchedulerViewModel.SophiaEndTimeCollection[i];
                    sophiaSubject = this.SchedulerViewModel.SophiaSubjectCollection[i];
                    sophiaLocation = this.SchedulerViewModel.SophiaLocationCollection[i];
                    sophiaResourceID = this.SchedulerViewModel.SophiaResourceIDCollection[i];
                    this.AppointmentBooking(sophiaStartTime, sophiaEndTime, sophiaSubject, sophiaLocation, sophiaResourceID);
                    await Process.Delay(1000);
                    AssistItem botMessage = new AssistItem() { Textual content = "Physician Sophia appointment efficiently booked.nThank you!", ShowAssistItemFooter = false };
                    this.SchedulerViewModel.Messages.Add(botMessage);
                }
            }
            
            for (int j = 0; j < this.SchedulerViewModel.JohnAvailableTimeSlots?.Rely; j++)
            {
                if (requeststring == this.SchedulerViewModel.JohnAvailableTimeSlots[j].ToString())
                {
                    johnStartTime = this.SchedulerViewModel.JohnStartTimeCollection[j];
                    johnEndTime = this.SchedulerViewModel.JohnEndTimeCollection[j];
                    johnSubject = this.SchedulerViewModel.JohnSubjectCollection[j];
                    johnLocation = this.SchedulerViewModel.JohnLocationCollection[j];
                    johnResourceID = this.SchedulerViewModel.JohnResourceIDCollection[j];
                    this.AppointmentBooking(johnStartTime, johnEndTime, johnSubject, johnLocation, johnResourceID);
                    await Process.Delay(1000);
                    AssistItem botMessage = new AssistItem() { Textual content = "Physician John appointment efficiently booked.nThank you!", ShowAssistItemFooter = false };
                    this.SchedulerViewModel.Messages.Add(botMessage);
                }
            }
        }
    }
}

Now, consult with the next code instance so as to add appointments within the .NET MAUI Scheduler.

AssistViewBehavior.cs

non-public void AppointmentBooking(DateTime startTime, DateTime endTime, string topic, string location, string resourceID)
{
    this.Scheduler!.DisplayDate = startTime;
    this.SchedulerViewModel?.Appointments?.Add(new SchedulerAppointment()
    {
        StartTime = startTime,
        EndTime = endTime,
        Topic = topic,
        Location = location,
        ResourceIds = new ObservableCollection
        Background = resourceID == "1000" ? new SolidColorBrush(Shade.FromArgb("#36B37B")) : new SolidColorBrush(Shade.FromArgb("#8B1FA9")),
    });

    (this.Scheduler.AppointmentsSource as ObservableCollection<schedulerappointment>)?.addrange(this.schedulerviewmodel?.appointments); 
}

Check with the next output picture.

Booking appointments with the AI-powered smart .NET MAUI Scheduler 
Reserving appointments with the AI-powered sensible .NET MAUI Scheduler

Supercharge your cross-platform apps with Syncfusion’s strong .NET MAUI controls.

Strive It Free

GitHub reference

Additionally, consult with the AI-powered sensible .NET MAUI Scheduler GitHub demo.

Conclusion

Thanks for studying! On this weblog, we’ve seen simply guide appointments by integrating AI-powered sensible options within the Syncfusion .NET MAUI Scheduler management. Check out the steps on this weblog and share your suggestions within the feedback part beneath. 

This function is included within the newest 2024 Quantity 3 launch. For extra particulars, go to our Launch Notes and What’s New pages.

The prevailing clients can obtain the newest model of Important Studio from the License and Downloads web page. If you’re new, strive our 30-day free trial to discover our unbelievable options. 

In case you have questions, you’ll be able to contact us by means of our assist discussion boardsuggestions portal, or assist portal. We’re at all times glad to help you!

Associated blogs

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments