Skip to content

Commit

Permalink
Update sidebar to form (#45)
Browse files Browse the repository at this point in the history
* feat: possible to render different input fields based on selected value on HelpSelect(WIP)

* feat: render fields based on helpSelect

* feat: inputList component

* fix: correct indexing when deleting elements

* feat: list of requirements now works with the prompt

* fix: updated styling for remove requirement button

* fix: requirements colors match select

* feat: validation employee selected

* fix: iconbutton type can now be set

* fix: idepentent iconbutton

* fix: revert button
  • Loading branch information
TrymVei authored Dec 5, 2023
1 parent feede6c commit 21b23ed
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 72 deletions.
1 change: 1 addition & 0 deletions app/salesGPT/components/employeeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ function EmployeeSelect({

return (
<Select
required
options={options}
isSearchable={true}
value={selectedOption}
Expand Down
4 changes: 4 additions & 0 deletions app/salesGPT/components/inputLIst/inputList.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.button-add {
background-color: transparent;
border: none;
}
68 changes: 68 additions & 0 deletions app/salesGPT/components/inputLIst/inputList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import styles from "./inputList.module.scss";
import AddIcon from "../../../icons/add.svg";
import { InputListValue } from "../../types";
import InputListItem from "./inputListItem/inputListItem";
import { SalesGPTIconButton } from "../salesGPTIconButton";

type InputListProps = {
inputListValues: InputListValue[];
setInputListValues: React.Dispatch<React.SetStateAction<InputListValue[]>>;
};

const InputList = ({ inputListValues, setInputListValues }: InputListProps) => {
function addValue(value: string) {
const updatedValues: InputListValue[] = [
...inputListValues,
{ index: inputListValues.length, value },
];
setInputListValues(updatedValues);
}

function updateValue(index: number, newValue: string) {
const updatedValues = [...inputListValues];
updatedValues[index] = { index, value: newValue };
setInputListValues(updatedValues);
}

function deleteValue(valueToDelete: string) {
let updatedValues: InputListValue[] = [];
inputListValues.map((value) => {
if (value.value !== valueToDelete) {
updatedValues.push(value);
}
});
updateIndex(updatedValues);
}

function updateIndex(listToUpdate: InputListValue[]) {
let updatedIndexValues: InputListValue[] = [];
listToUpdate.map((inputListValue, index) => {
updatedIndexValues.push({ index: index, value: inputListValue.value });
});
setInputListValues(updatedIndexValues);
}

return (
<>
{inputListValues.map((inputListValue) => {
return (
<InputListItem
key={inputListValue.index}
updateValue={updateValue}
deleteValue={deleteValue}
InputListValue={inputListValue}
/>
);
})}
<SalesGPTIconButton
role="button"
className={styles["button-add"]}
text={""}
icon={<AddIcon />}
onClick={() => addValue("")}
/>
</>
);
};

export default InputList;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.input-list-item {
display: flex;
flex-direction: row;
align-items: center;
}

.label-input {
padding-right: 6px;
}

@mixin sharedStyle {
font-size: 1rem;

border: 0.5px solid white;
padding: 1rem;

height: 48px;

color: black;
background-color: white;
}

input[type="text"].input {
@include sharedStyle();

width: 100%;

border-radius: 10px 0 0 10px;

text-align: left;

background-color: white;
color: black;
}

.button-remove {
@include sharedStyle();

border-radius: 0 10px 10px 0;
}
42 changes: 42 additions & 0 deletions app/salesGPT/components/inputLIst/inputListItem/inputListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { InputListValue } from "@/app/salesGPT/types";
import styles from "./inputListItem.module.scss";
import CloseIcon from "../../../../icons/close.svg";
import { SalesGPTIconButton } from "../../salesGPTIconButton";

type ListInputProps = {
InputListValue: InputListValue;
updateValue: Function;
deleteValue: Function;
};

const ListInput = ({
InputListValue,
updateValue,
deleteValue,
}: ListInputProps) => {
return (
<div className={styles["input-list-item"]}>
<label className={styles["label-input"]} htmlFor="requirements">
{InputListValue.index + 1}:
</label>

<input
className={styles["input"]}
type="text"
id="requirements"
placeholder={""}
value={InputListValue.value}
onChange={(e) => updateValue(InputListValue.index, e.target.value)}
/>

<SalesGPTIconButton
role="button"
className={styles["button-remove"]}
icon={<CloseIcon />}
onClick={() => deleteValue(InputListValue.value)}
/>
</div>
);
};

export default ListInput;
163 changes: 91 additions & 72 deletions app/salesGPT/components/salesGPT.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
"use client";
import React, { useEffect, useState } from "react";
import { Loading } from "@/app/components/chatHomepage";
import { EmployeeItem, HelpOption, HelpOptionValue } from "../types";
import {
EmployeeItem,
HelpOption,
HelpOptionValue,
InputListValue,
} from "../types";
import EmployeeCVSummary from "./employeeCVSummary";
import { ErrorBoundary } from "../../components/error";
import {
Expand All @@ -26,6 +31,8 @@ import RightPane from "./rightPane";
import RequirementsList from "./requirementsList";
import { SALES_GPT_MASK } from "@/app/masks/no";
import { projectExperienceToText } from "@/app/function/ProjectExperienceToText";
import InputList from "./inputLIst/inputList";
import { SalesGPTIconButton } from "./salesGPTIconButton";

const availableHelp: HelpOption[] = [
{
Expand Down Expand Up @@ -55,7 +62,6 @@ function _SalesGPT() {
EmployeeItem | undefined
>(undefined);

const [requirementText, setRequirementText] = useState("");
const [requirementResponse, setRequirementResponse] = useState<
RequirementResponse[]
>([]);
Expand All @@ -64,13 +70,17 @@ function _SalesGPT() {
const [isAnalysisLoading, setIsAnalysisLoading] = useState(false);

const [selectedHelp, setSelectedHelp] = useState<HelpOption | undefined>(
undefined,
availableHelp[0],
);

const [showCVSummary, setShowCVSummary] = useState(false);
const [showRequirementsList, setShowRequirementsList] = useState(false);
const [concise, setConcise] = useState(false);

const [inputListValues, setInputListValues] = useState<InputListValue[]>([
{ index: 0, value: "" },
]);

function handleSelectEmployee(newValue: EmployeeItem | undefined): void {
setSelectedEmployee(newValue);
// TODO: Handle query params later
Expand Down Expand Up @@ -202,7 +212,9 @@ function _SalesGPT() {
async function handleAnalyseButtonClick(): Promise<void> {
setIsAnalysisLoading(true);
setRequirementResponse([]);
const requirements = requirementText.split("\n").filter((s) => s.length);
const requirements = inputListValues.map(
(requirement) => requirement.value,
);
const employeeAlias = aliasFromEmail(selectedEmployee?.email);

if (selectedHelp?.value == HelpOptionValue.RequirementList) {
Expand Down Expand Up @@ -260,74 +272,81 @@ function _SalesGPT() {
>
<SalesSidebar title={title} subtitle={""}>
<div className={styles["sidebar-content"]}>
<div className={styles["input-field"]}>
<label htmlFor="choose-help">{Locale.SalesGPT.Help.Choose}</label>
<HelpSelect
options={availableHelp}
selectedHelp={selectedHelp}
handleSelectHelp={setSelectedHelp}
/>
</div>
<div className={styles["input-field"]}>
<label htmlFor="choose-employee">
{Locale.SalesGPT.ChooseEmployee}
</label>
<EmployeeSelect
employees={employees}
selectedEmployee={selectedEmployee}
handleSelectEmployee={handleSelectEmployee}
handleClear={handleClearSelectedEmployee}
/>
</div>
<div className={styles["input-field"]}>
<label htmlFor="requirements">{Locale.SalesGPT.Requirements}</label>
<textarea
id="requirements"
className={styles["text-input"]}
placeholder={Locale.SalesGPT.RequirementsPlaceholder}
value={requirementText}
onChange={(event) => setRequirementText(event.target.value)}
></textarea>
</div>
<div className={styles["input-field"]}>
<label htmlFor="summary">{Locale.SalesGPT.Summary}</label>
<textarea
id="requirements"
className={styles["text-input"]}
placeholder={Locale.SalesGPT.SummaryPlaceholder}
value={summaryText}
onChange={(event) => setSummaryText(event.target.value)}
></textarea>
</div>
<div className={styles["input-field"]}>
<label htmlFor="concise-answer">
{Locale.SalesGPT.ConciseOption}
</label>
<input
type="checkbox"
id="concise-answer"
checked={concise}
onChange={(event) => setConcise(event.target.checked)}
/>
</div>
<div className={styles["analyse-button-container"]}>
<IconButton
key="analyse"
bordered
className={styles["analyse-button"]}
text={Locale.SalesGPT.Analyse}
onClick={handleAnalyseButtonClick}
/>
</div>
<div className={styles["analyse-button-container"]}>
<IconButton
key="sendToChat"
bordered
className={styles["analyse-button"]}
text={Locale.SalesGPT.FromSalesGptToChat}
onClick={handleChatButtonClick}
/>
</div>
<form
onSubmit={(e) => {
e.preventDefault();
}}
>
<div className={styles["input-field"]}>
<label htmlFor="choose-help">{Locale.SalesGPT.Help.Choose}</label>
<HelpSelect
options={availableHelp}
selectedHelp={selectedHelp}
handleSelectHelp={setSelectedHelp}
/>
</div>
</form>

<form
onSubmit={(e) => {
e.preventDefault();
handleAnalyseButtonClick();
}}
>
<div className={styles["input-field"]}>
<label htmlFor="choose-employee">
{Locale.SalesGPT.ChooseEmployee}
</label>
<EmployeeSelect
employees={employees}
selectedEmployee={selectedEmployee}
handleSelectEmployee={handleSelectEmployee}
handleClear={handleClearSelectedEmployee}
/>
</div>

<div className={styles["input-field"]}>
<label htmlFor="requirements">
{Locale.SalesGPT.Requirements}
</label>
<InputList
inputListValues={inputListValues}
setInputListValues={setInputListValues}
/>
</div>

{/* TODO: Kanskje dele opp koden så vi har en getField som rendrer basert på selectedHelp. lettere hvis vi endrer på value */}
{selectedHelp?.value !== "requirementlist" && (
<div className={styles["input-field"]}>
<label htmlFor="summary">{Locale.SalesGPT.Summary}</label>
<textarea
id="requirements"
className={styles["text-input"]}
placeholder={Locale.SalesGPT.SummaryPlaceholder}
value={summaryText}
onChange={(event) => setSummaryText(event.target.value)}
></textarea>
</div>
)}
<div className={styles["analyse-button-container"]}>
<SalesGPTIconButton
key="analyse"
bordered
className={styles["analyse-button"]}
text={Locale.SalesGPT.Analyse}
role="submit"
/>
</div>
<div className={styles["analyse-button-container"]}>
<IconButton
key="sendToChat"
bordered
className={styles["analyse-button"]}
text={Locale.SalesGPT.FromSalesGptToChat}
onClick={handleChatButtonClick}
/>
</div>
</form>
</div>
<IconButton
text={"Tilbake til chat"}
Expand Down
Loading

0 comments on commit 21b23ed

Please sign in to comment.