Skip to content

Commit

Permalink
Refactored chat interface and updated employee form
Browse files Browse the repository at this point in the history
1. Updated the chat interface to include sender information in the `chatStore`. The `Prompt` interface was renamed to `Message` and a `sender` field was added. The `addPrompt` function was also updated to `addMessage`, now taking a `sender` and `text` as parameters.

2. Refactored the `EmployeeForm` component to replace the `orgCategoryStore` with the `positionStore`.

3. Renamed `Chat.vue` to `ChatAssistant.vue` and updated the component to display messages in a card format with sender information. Added functionality to automatically scroll to the most recent message.

4. Added `Position` interface in `officeFrameTypes.ts`.

5. Created a new `positionStore` for handling position related data.

6. Updated the router configuration to reflect the new `ChatAssistant` component name.

Please note, the `positionStore` is a placeholder and its methods and calls need to be properly implemented to function correctly.
  • Loading branch information
kneoio committed Jul 15, 2024
1 parent bf0b053 commit b7681b2
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
<n-gi span="24" class="chat-section">
<n-grid x-gap="12" y-gap="12" class="chat-grid">
<n-gi span="24" class="chat-messages">
<div v-for="msg in chatStore.currentChat.prompts" :key="msg.id" class="message">
{{ msg.text }}
</div>
<div v-if="chatStore.currentChat.content" class="message">
{{ chatStore.currentChat.content }}
</div>
<n-scrollbar style="max-height: 300px;">
<n-space vertical>
<n-card v-for="msg in chatStore.currentChat.messages" :key="msg.id" size="small" :title="msg.sender">
{{ msg.text }}
</n-card>
</n-space>
</n-scrollbar>
</n-gi>
<n-gi span="24" class="chat-input">
<n-input v-model="message" placeholder="Type your message" style="width: 100%; max-width: 600px;"/>
Expand All @@ -38,7 +39,7 @@
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';
import { defineComponent, ref, onMounted, nextTick } from 'vue';
import { useRouter } from 'vue-router';
import {
NButton,
Expand All @@ -48,12 +49,15 @@ import {
NGrid,
NGi,
NH2,
NCard,
NSpace,
NScrollbar
} from 'naive-ui';
import { ArrowBigLeft } from '@vicons/tabler';
import { useChatStore } from '../../stores/chatStore'; // adjust the import path as needed
import { useChatStore } from '../../stores/chatStore';
export default defineComponent({
name: 'KneoProjectForm',
name: 'ChatAssistant',
components: {
NButtonGroup,
NInput,
Expand All @@ -62,6 +66,9 @@ export default defineComponent({
NGrid,
NGi,
NH2,
NCard,
NSpace,
NScrollbar,
ArrowBigLeft,
},
setup() {
Expand All @@ -71,22 +78,37 @@ export default defineComponent({
const handleSaveChat = () => {
chatStore.saveChat();
router.push('/ai/chat');
};
const goBack = () => {
router.push('/ai/chat');
router.push('/dashboard');
};
const sendMessage = async () => {
if (message.value.trim()) {
chatStore.addPrompt(`You: ${message.value}`);
chatStore.addMessage('You', message.value);
const response = await chatStore.dummyApiRequest(message.value);
chatStore.addPrompt(response); // Add bot response as a new prompt
chatStore.addMessage('Assistant', response);
message.value = '';
// Scroll to the bottom after adding new messages
await nextTick(() => {
const chatMessages = document.querySelector('.chat-messages');
if (chatMessages) {
chatMessages.scrollTop = chatMessages.scrollHeight;
}
});
}
};
onMounted(() => {
// Scroll to the bottom when component is mounted
const chatMessages = document.querySelector('.chat-messages');
if (chatMessages) {
chatMessages.scrollTop = chatMessages.scrollHeight;
}
});
return {
handleSaveChat,
goBack,
Expand Down Expand Up @@ -114,7 +136,7 @@ export default defineComponent({
.chat-grid {
display: flex;
flex-direction: column;
height: 300px;
height: 400px;
}
.chat-messages {
Expand All @@ -130,8 +152,4 @@ export default defineComponent({
align-items: center;
gap: 8px;
}
.message {
margin-bottom: 8px;
}
</style>
</style>
12 changes: 6 additions & 6 deletions src/components/forms/EmployeeForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import {
} from 'naive-ui';
import {ArrowBigLeft} from '@vicons/tabler';
import {Employee, EmployeeSave} from "../../types/officeFrameTypes";
import {useOrgCategoryStore} from "../../stores/of/orgCategoryStore";
import {usePositionStore} from "../../stores/of/positionStore";
import {useEmployeeStore} from "../../stores/of/employeeStore";
export default defineComponent({
Expand All @@ -103,6 +103,7 @@ export default defineComponent({
const route = useRoute();
const router = useRouter();
const store = useEmployeeStore();
const positionStore = usePositionStore();
const activeTab = ref('properties');
const localFormData = reactive<Employee>({
name: "", userId: 0,
Expand All @@ -121,12 +122,11 @@ export default defineComponent({
rank: 0
});
const categoryOptions = computed(() =>
orgCategoryStore.getEntries.map(category => ({
label: category.identifier,
value: category.id
positionStore.getEntries.map(d => ({
label: d.identifier,
value: d.id
}))
);
const orgCategoryStore = useOrgCategoryStore();
const handleSave = async () => {
loadingBar.start();
Expand Down Expand Up @@ -181,7 +181,7 @@ export default defineComponent({
localFormData.position = {id: '', identifier: '', localizedName: ''};
localFormData.rank = 0;
}
await orgCategoryStore.fetchOrgCategories();
await positionStore.fetchAll();
});
return {
Expand Down
2 changes: 1 addition & 1 deletion src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ProjectsAndTasks from '../components/outlines/ProjectAndTasks.vue';
import ProjectsList from '../components/lists/ProjectsList.vue';
import ProjectForm from '../components/forms/ProjectForm.vue';
import AiAssistant from "../components/outlines/AiAssistant.vue";
import ChatAssistant from "../components/forms/Chat.vue";
import ChatAssistant from "../components/forms/ChatAssistant.vue";
import References from "../components/outlines/References.vue";
import OrganizationsList from "../components/lists/OrganizationsList.vue";
import EmployeeList from "../components/lists/EmployeeList.vue";
Expand Down
36 changes: 18 additions & 18 deletions src/stores/chatStore.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';

interface Prompt {
interface Message {
id: number;
sender: string;
text: string;
}

interface Chat {
id: number;
content: string;
prompts: Prompt[];
messages: Message[];
}

export const useChatStore = defineStore('chatStore', () => {
const chats = ref<Chat[]>([]);
const currentChat = ref<Chat>({
id: Date.now(),
content: '',
prompts: [],
messages: [],
});

const addPrompt = (prompt: string) => {
currentChat.value.prompts.push({ id: Date.now(), text: prompt });
};

const addContent = (content: string) => {
currentChat.value.content += content;
const addMessage = (sender: string, text: string) => {
currentChat.value.messages.push({
id: Date.now(),
sender,
text,
});
};

const saveChat = () => {
chats.value.push({ ...currentChat.value, id: Date.now() });
currentChat.value.content = '';
currentChat.value.prompts = [];
chats.value.push({ ...currentChat.value });
currentChat.value = {
id: Date.now(),
messages: [],
};
};

const dummyApiRequest = (prompt: string): Promise<string> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`Bot: Response to "${prompt}"`);
resolve(`Response to "${prompt}"`);
}, 1000);
});
};

return {
chats,
currentChat,
addPrompt,
addContent,
addMessage,
saveChat,
dummyApiRequest,
};
});
});
94 changes: 94 additions & 0 deletions src/stores/of/positionStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import {defineStore} from 'pinia';
import {ref, computed} from 'vue';
import apiClient, {setupApiClient} from '../../api/apiClient';
import {ApiFormResponse, ApiViewPageResponse} from "../../types";
import {Organization, OrganizationSave, Position} from "../../types/officeFrameTypes";

export const usePositionStore = defineStore('positionStore', () => {
const apiViewResponse = ref<ApiViewPageResponse<Position> | null>(null);
const apiFormResponse = ref<ApiFormResponse | null>(null);

const getEntries = computed(() => {
return apiViewResponse.value?.viewData.entries || [];
});

const getCurrent = computed(() => {
const defaultData = {
regDate: '',
lastModifiedDate: '',
identifier: ''
};
return apiFormResponse.value?.docData || defaultData;
});

const getPagination = computed(() => {
if (!apiViewResponse.value) {
return {
page: 1,
pageSize: 10,
itemCount: 0,
pageCount: 1,
showSizePicker: true,
pageSizes: [10, 20, 30, 40]
};
}

const { viewData } = apiViewResponse.value;
return {
page: viewData.pageNum,
pageSize: viewData.pageSize,
itemCount: viewData.count,
pageCount: viewData.maxPage,
showSizePicker: true,
pageSizes: [10, 20, 30, 40]
};
});

const fetchOrgCategories = async (page = 1, pageSize = 10) => {
const response = await apiClient.get(`/positions?page=${page}&size=${pageSize}`);
if (response && response.data && response.data.payload) {
apiViewResponse.value = response.data.payload;
} else {
throw new Error('Invalid API response structure');
}
};

const fetchOrgCategory = async (id: string) => {
const response = await apiClient.get(`/positions/${id}`);
if (response && response.data && response.data.payload) {
apiFormResponse.value = response.data.payload;
} else {
throw new Error('Invalid API response structure');
}
};

const updateCurrent = (data: Organization, actions: any = {}) => {
apiFormResponse.value = {
docData: data,
actions: actions
};
};

const save = async (data: OrganizationSave, id?: string) => {
const response = await apiClient.post(`/positions/${id}`, data);
if (response && response.data) {
const { docData } = response.data;
updateCurrent(docData, {});
return docData;
} else {
throw new Error('Invalid API response structure');
}
};

return {
apiViewResponse,
apiFormResponse,
setupApiClient,
fetchAll: fetchOrgCategories,
fetch: fetchOrgCategory,
save,
getEntries,
getPagination,
getCurrent
};
});
6 changes: 6 additions & 0 deletions src/types/officeFrameTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,9 @@ export interface OrgCategory {
localizedName: Record<string, string>;
}

export interface Position {
id?: string;
identifier: string;
localizedName: Record<string, string>;
}

0 comments on commit b7681b2

Please sign in to comment.