Code viewer for World: Practical 2-1 Nakyung Kim
// Cloned by Nakyung Kim on 20 Nov 2023 from World "Chat with GPT model" by Starter user

//Api key Credit : https://platform.openai.com/api-keys
const openaiURL = "https://api.openai.com/v1/chat/completions";
const themodel = "gpt-3.5-turbo";
var apikey = "";
var theprompt = "Hello World";
var initialCheckPassed = false;

$("body").css({ margin: "20px", padding: "20px" });

// Write HTML content dynamically
//Source of the backgrounds:
//https://www.freepik.com/free-vector/purple-color-gradient-background-designs-modern_34150613.htm
document.write(`
  <div id="enterkey" style="background-image: url('/uploads/jackie2002/6.jpg'); border-radius: 20px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19);">
  <br>

  <!-- Enter API Key Section -->
  <div id="enterkey">
    <h1  style="color:white;">Chat with GPT model</h1>
    <b  style="color:white;">Enter API key: </b>
       <br>
          <br>
    <input style='width:25vw;' maxlength='2000' name="apikey" id="apikey" value=''>  
    <button onclick='setApiKey();' class='ab-normbutton'>Set API key</button>
    <div style="color:white;"  id="enter"></div>  
    <div style="color:white;">
    <br>
  <!-- Temperature Slider Section -->
  <label for="temperatureSlider" style="font-size:22px;" >Adjust Temperature:</label>
    <br>
  <input type="range" id="temperatureSlider" name="temperatureSlider" min="0" max="1" step="0.1" value="0.7">
    <br>
  <span id="temperatureValue" style="font-size:22px;">0.7</span>
</div>


<!-- Chat Input Section -->
<div style="width:60vw; background-color: rgba(255, 255, 255, 0.5); margin: 20px; padding: 20px; border-radius: 20px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19);">
  <h3 style="color:white;">Interact with AI</h3>
<input style="width:50vw; opacity: 1;" id="me" value="How much is the average living cost in Dublin?" onclick="clearInput(this);">

  <button onclick="sendChat();" class='ab-normbutton' style="opacity: 1;">Send</button> 
</div>

<!-- Chat Output Section -->
<div style="width:60vw; background-color: rgba(148, 108, 222, 0.5); margin: 20px; padding: 20px; border-radius: 20px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19);">
  <h3 style="color: white; opacity: 1;">GPT replies</h3>
  <div id="them" style="opacity: 1;"></div>
</div>

<br>
  </div>
  </div>
`);
$(document).ready(function () {
  applyInitialStyles();
  attachEventHandlers();
});

function applyInitialStyles() {
  $("body").css({
    display: "flex",
    "flex-direction": "column",
    "align-items": "center",
    "justify-content": "center",
    height: "150vh",
    margin: "0",
    padding: "20px",
    "text-align": "center",
    "font-family":
      "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif", // macOS style font
  });

  //Temperature Slider bar css Credit : https://www.w3schools.com/howto/howto_js_rangeslider.asp
  $("#temperatureSlider").css({
    width: "100%", // Full width of the container for better usability
    height: "2px", // Height of the slider track
    background: "white", // White track
    "border-radius": "5px", // Slightly rounded corners for the track
    outline: "none", // Removes the default focus outline
    opacity: "0.7", // Slightly transparent track
    transition: "opacity 0.2s", // Smooth transition for the thumb
  });
  $("input").css({
    "text-align": "center",
    width: "calc(100% - 40px)",
    margin: "10px 20px",
    padding: "10px",
    "border-radius": "20px",
    border: "none",
    "box-shadow":
      "0 4px 8px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19)",
  });

  $("button")
    .css({
      display: "block",
      margin: "10px auto",
      padding: "10px 20px",
      "background-color": "#686AB7",
      color: "white",
      border: "none",
      "border-radius": "20px",
      "box-shadow":
        "0 4px 8px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19)",
      cursor: "pointer",
    })
    .hover(
      function () {
        $(this).css("opacity", "0.8");
      },
      function () {
        $(this).css("opacity", "1");
      }
    );

  // Hover effect for buttons
  $("button").hover(
    function () {
      $(this).css("opacity", "0.8");
    },
    function () {
      $(this).css("opacity", "1");
    }
  );

  $("#them").css({
    color: "white",
    width: "60vw",
    "min-height": "100px",
  });

  $(".chat-section, .output-section").css({
    "max-width": "60vw",
    width: "100%",
    "border-radius": "20px",
  });

  if (window.matchMedia("(max-width: 600px)").matches) {
    $(".chat-section, .output-section").css({
      "border-radius": "10px",
      padding: "15px",
    });
  }
}

function attachEventHandlers() {
  $("#me").keydown(function (event) {
    if (event.keyCode == 13) sendChat();
  });

  $("#me").click(function () {
    clearInput(this);
  });

  $("#apikey").click(function () {
    setApiKey();
  });
}

function clearInput(element) {
  element.value = "";
}

function setApiKey() {
  apikey = $("#apikey").val().trim();
  if (apikey === "") {
    $("#enter").html("<b>Please enter the correct API key.</b>");
  } else {
    $("#enter").html("<b>API key has been set.</b>");
    $("#apikey").prop("readonly", true);
  }
}

function sendChat() {
  theprompt = $("#me").val();
  var temperature = $("#temperatureSlider").val();

  if (!apikey) {
    $("#them").html("<b>Please set the API key first.</b>");
    return;
  }

  if (!initialCheckPassed && theprompt !== "Hello World") {
    $("#them").html("<b>Please enter 'Hello World' to call the API.</b>");
    return;
  }

  initialCheckPassed = true;
  makeApiCall(theprompt, temperature);
}

//Set the temperature manage tool : https://platform.openai.com/docs/guides/text-generation/reproducible-outputs
function makeApiCall(prompt, temperature) {
  var requestData = {
    model: themodel,
    temperature: parseFloat(temperature),
    messages: [{ role: "user", content: prompt }],
  };

  $.ajaxSetup({
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer " + apikey,
    },
  });

  $.ajax({
    type: "POST",
    url: openaiURL,
    data: JSON.stringify(requestData),
    dataType: "json",
    success: handleSuccess,
    error: handleError,
  });
}

$("#temperatureSlider").on("input change", function () {
  $("#temperatureValue").text($(this).val());
});

function handleSuccess(data) {
  var answer = data.choices[0].message.content;
  $("#them").html(answer);
}

function handleError() {
  $("#them").html("<b>An error occurred. Please try again.</b>");
}