Selaa lähdekoodia

zbytest003-2025-02-18 06:46:33

genlitex 2 kuukautta sitten
vanhempi
sitoutus
43a9576fbc

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index-BWZxfZmd.css


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 4 - 0
dist/assets/index-CeEILHzB.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 4
dist/assets/index-malWbV8K.js


+ 2 - 2
dist/index.html

@@ -4,8 +4,8 @@
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>Prototype Design</title>
-    <script type="module" crossorigin src="/prototype/3000/assets/index-malWbV8K.js"></script>
-    <link rel="stylesheet" crossorigin href="/prototype/3000/assets/index-Btspm7_H.css">
+    <script type="module" crossorigin src="/ide/proxy/6004/assets/index-CeEILHzB.js"></script>
+    <link rel="stylesheet" crossorigin href="/ide/proxy/6004/assets/index-BWZxfZmd.css">
   </head>
   <body>
     <div id="app"></div>

+ 12 - 0
src/router/index.js

@@ -1,11 +1,23 @@
 import { createRouter, createWebHashHistory } from 'vue-router'
 import HomeView from '../views/HomeView.vue'
+import LoginView from '../views/LoginView.vue'
+import ChatView from '../views/ChatView.vue'
 
 const routes = [
   {
     path: '/',
     name: 'home',
     component: HomeView
+  },
+  {
+    path: '/login',
+    name: 'login',
+    component: LoginView
+  },
+  {
+    path: '/chat',
+    name: 'chat',
+    component: ChatView
   }
 ]
 

+ 133 - 0
src/views/ChatView.vue

@@ -0,0 +1,133 @@
+<template>
+  <div class="chat-container">
+    <div class="messages">
+      <div v-for="(message, index) in messages" :key="index" :class="['message', {'user-message': message.fromUser}, {'system-message': !message.fromUser}]">
+        <span class="message-content">{{ message.content }}</span>
+      </div>
+    </div>
+    <a-form @submit.prevent="sendMessage">
+      <a-form-item>
+        <a-input v-model:value="messageText" placeholder="Type your message..."></a-input>
+      </a-form-item>
+      <a-form-item>
+        <a-button type="primary" html-type="submit">Send</a-button>
+      </a-form-item>
+    </a-form>
+    <a-upload
+      name="file"
+      :multiple="true"
+      :before-upload="beforeUpload"
+      @change="handleChange">
+      <template #uploadButton>
+        <a-button>
+          <upload-outlined /> Upload File
+        </a-button>
+      </template>
+    </a-upload>
+  </div>
+</template>
+
+<script>
+import { ref } from 'vue';
+import { notification } from 'ant-design-vue';
+
+export default {
+  name: 'ChatView',
+  setup() {
+    const messages = ref([
+      { content: 'Welcome to the chat!', fromUser: false },
+    ]);
+    const messageText = ref('');
+    const file = ref(null);
+
+    const sendMessage = () => {
+      if (messageText.value.trim()) {
+        messages.value.push({ content: messageText.value, fromUser: true });
+        messageText.value = '';
+        // Simulate system response
+        setTimeout(() => {
+          messages.value.push({ content: 'Received your message.', fromUser: false });
+        }, 1000);
+      } else {
+        notification.warning({
+          message: 'Warning',
+          description: 'Please enter a message.',
+        });
+      }
+    };
+
+    const beforeUpload = (file) => {
+      // Handle file upload logic here
+      return false; // Prevent default upload
+    };
+
+    const handleChange = (info) => {
+      if (info.file.status === 'done') {
+        notification.success({
+          message: 'Success',
+          description: `${info.file.name} file uploaded.`,
+        });
+      } else if (info.file.status === 'error') {
+        notification.error({
+          message: 'Error',
+          description: `${info.file.name} file upload failed.`,
+        });
+      }
+    };
+
+    return {
+      messages,
+      messageText,
+      sendMessage,
+      beforeUpload,
+      handleChange,
+      file,
+    };
+  },
+};
+</script>
+
+<style scoped>
+.chat-container {
+  width: 100%;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20px;
+  background-color: #f0f2f5; /* Background color */
+}
+
+.messages {
+  width: 100%;
+  max-height: 70vh;
+  overflow-y: scroll;
+  border: 1px solid #ccc;
+  border-radius: 8px;
+  padding: 10px;
+  background-color: white;
+}
+
+.message {
+  margin: 10px 0;
+  padding: 10px;
+  border-radius: 5px;
+}
+
+.user-message {
+  background-color: #e6f7ff; /* User message background color */
+}
+
+.system-message {
+  background-color: #fff3cd; /* System message background color */
+}
+
+.message-content {
+  font-size: 14px;
+}
+
+.a-upload {
+  margin-top: 20px;
+}
+</style>

+ 103 - 0
src/views/LoginView.vue

@@ -0,0 +1,103 @@
+<template>
+  <div class="login-container">
+    <a-form :model="formState" :rules="rules" @submit.prevent="handleLogin">
+      <a-form-item prop="username">
+        <a-input v-model:value="formState.username" placeholder="Username" />
+      </a-form-item>
+      <a-form-item prop="password">
+        <a-input-password v-model:value="formState.password" placeholder="Password" />
+      </a-form-item>
+      <a-form-item>
+        <a-checkbox v-model:checked="formState.rememberMe">Remember me</a-checkbox>
+      </a-form-item>
+      <a-button type="primary" html-type="submit" class="login-button">
+        Login
+      </a-button>
+    </a-form>
+  </div>
+</template>
+
+<script>
+import { reactive, ref } from 'vue';
+import { useRouter } from 'vue-router';
+import { notification } from 'ant-design-vue';
+
+export default {
+  name: 'LoginView',
+  setup() {
+    const router = useRouter();
+    const formState = reactive({
+      username: 'admin',
+      password: 'admin123',
+      rememberMe: false,
+    });
+
+    const rules = {
+      username: [
+        { required: true, message: 'Please input your username!', trigger: 'blur' },
+        { min: 4, max: 16, message: 'Length should be 4-16 characters', trigger: 'blur' },
+        { pattern: /^[a-zA-Z0-9]+$/, message: 'Special characters are not allowed', trigger: 'blur' },
+      ],
+      password: [
+        { required: true, message: 'Please input your password!', trigger: 'blur' },
+        { min: 6, max: 20, message: 'Length should be 6-20 characters', trigger: 'blur' },
+      ],
+    };
+
+    const handleLogin = () => {
+      if (formState.username === 'admin' && formState.password === 'admin123') {
+        router.push('/');
+        if (formState.rememberMe) {
+          localStorage.setItem('rememberMe', true);
+        }
+      } else {
+        notification.error({
+          message: 'Error',
+          description: 'Username or password is incorrect.',
+        });
+      }
+    };
+
+    return {
+      formState,
+      rules,
+      handleLogin,
+    };
+  },
+};
+</script>
+
+<style scoped>
+.login-container {
+  width: 100%;
+  height: 100vh;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #f0f2f5; /* Added background color */
+  padding: 20px; /* Added padding */
+}
+.login-button {
+  margin-top: 24px;
+}
+.login-form {
+  background-color: white; /* Added form background color */
+  border-radius: 8px; /* Rounded corners */
+  box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); /* Shadow effect */
+  padding: 20px; /* Padding inside the form */
+}
+.login-input {
+  margin-bottom: 10px; /* Spacing between inputs */
+}
+.login-label {
+  font-weight: bold; /* Bold labels */
+}
+.login-error {
+  color: red; /* Error messages in red */
+  margin-top: 10px; /* Space above error messages */
+}
+
+.login-button {
+  margin-top: 24px;
+}
+</style>

+ 160 - 0
src/views/MainContent.vue

@@ -0,0 +1,160 @@
+<template>
+  <div class="main-content-container">
+    <div class="chat-interface">
+      <div class="chat-messages">
+        <div v-for="(message, index) in messages" :key="index" :class="['message', {'user-message': message.fromUser}, {'system-message': !message.fromUser}]>
+          <span class="message-content">{{ message.content }}</span>
+        </div>
+      </div>
+      <a-form @submit.prevent="sendMessage">
+        <a-form-item>
+          <a-input v-model:value="messageText" placeholder="Type your message..."></a-input>
+        </a-form-item>
+        <a-form-item>
+          <a-button type="primary" html-type="submit">Send</a-button>
+        </a-form-item>
+      </a-form>
+    </div>
+    <div class="documents-section">
+      <h2>Documents</h2>
+      <ul>
+        <li v-for="document in documents" :key="document.id">
+          <a href="#" @click="viewDocument(document)">
+            <i class="far fa-file"></i> {{ document.name }}
+          </a>
+          <button @click="deleteDocument(document.id)">Delete</button>
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+
+<script>
+import { ref } from 'vue';
+
+export default {
+  name: 'MainContent',
+  setup() {
+    const messages = ref([
+      { content: 'Welcome to the chat!', fromUser: false },
+    ]);
+    const messageText = ref('');
+    const documents = ref([
+      { id: 1, name: 'Document 1.pdf' },
+      { id: 2, name: 'Document 2.docx' },
+    ]);
+
+    const sendMessage = () => {
+      if (messageText.value.trim()) {
+        messages.value.push({ content: messageText.value, fromUser: true });
+        messageText.value = '';
+        // Simulate system response
+        setTimeout(() => {
+          messages.value.push({ content: 'Received your message.', fromUser: false });
+        }, 1000);
+      } else {
+        notification.warning({
+          message: 'Warning',
+          description: 'Please enter a message.',
+        });
+      }
+    };
+
+    const viewDocument = (document) => {
+      console.log(`Viewing document: ${document.name}`);
+      // Logic to view the document
+    };
+
+    const deleteDocument = (documentId) => {
+      console.log(`Deleting document with ID: ${documentId}`);
+      // Logic to delete the document
+    };
+
+    return {
+      messages,
+      messageText,
+      sendMessage,
+      documents,
+      viewDocument,
+      deleteDocument,
+    };
+  },
+};
+</script>
+
+<style scoped>
+.main-content-container {
+  margin-left: 250px;
+  width: calc(100% - 250px);
+  height: 100%;
+  background-color: grey;
+  padding: 20px;
+  box-sizing: border-box;
+  display: flex;
+  flex-direction: column;
+}
+
+.chat-interface {
+  flex-grow: 1;
+  display: flex;
+  flex-direction: column;
+}
+
+.chat-messages {
+  flex-grow: 1;
+  overflow-y: auto;
+  border: 1px solid #ccc;
+  border-radius: 8px;
+  padding: 10px;
+  background-color: white;
+}
+
+.message {
+  margin: 10px 0;
+  padding: 10px;
+  border-radius: 5px;
+}
+
+.user-message {
+  background-color: #e6f7ff; /* User message background color */
+}
+
+.system-message {
+  background-color: #fff3cd; /* System message background color */
+}
+
+.message-content {
+  font-size: 14px;
+}
+
+.documents-section {
+  margin-top: 20px;
+}
+
+.documents-section h2 {
+  margin-bottom: 10px;
+}
+
+.documents-section ul {
+  list-style: none;
+  padding: 0;
+}
+
+.documents-section li {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.documents-section a {
+  display: flex;
+  align-items: center;
+  color: blue;
+  text-decoration: none;
+}
+
+.documents-section i {
+  margin-right: 5px;
+}
+</style>

+ 209 - 0
src/views/Sidebar.vue

@@ -0,0 +1,209 @@
+<template>
+  <div class="sidebar-container">
+    <div class="fixed-requirements">
+      <h2>Fixed Requirements</h2>
+      <ul>
+        <li>Requirement 1</li>
+        <li>Requirement 2</li>
+        <li>Requirement 3</li>
+      </ul>
+    </div>
+    <div class="requirements-list">
+      <h2>Requirements</h2>
+      <ul>
+        <li v-for="(requirement, index) in requirements" :key="index" @click="selectRequirement(requirement)">{{ requirement.title }}</li>
+      </ul>
+    </div>
+    <button class="add-new-requirement-button" @click="addNewRequirement">Add New Requirement</button>
+    <button class="toggle-sidebar-button" @click="toggleSidebar"><i class="fas fa-angle-double-left"></i></button>
+    <transition name="slide">
+      <div v-if="isSidebarExpanded" class="expanded-sidebar">
+        <div class="expanded-requirements">
+          <h2>Expanded Requirements</h2>
+          <ul>
+            <li v-for="(requirement, index) in expandedRequirements" :key="index" @click="selectExpandedRequirement(requirement)">{{ requirement.title }}</li>
+          </ul>
+        </div>
+      </div>
+    </transition>
+  </div>
+</template>
+
+<script>
+import { ref } from 'vue';
+
+export default {
+  name: 'Sidebar',
+  setup() {
+    const requirements = ref([
+      { title: 'Requirement 1', details: 'Details for Requirement 1' },
+      { title: 'Requirement 2', details: 'Details for Requirement 2' },
+      { title: 'Requirement 3', details: 'Details for Requirement 3' },
+    ]);
+
+    const expandedRequirements = ref([]);
+
+    const selectRequirement = (requirement) => {
+      console.log(`Selected requirement: ${requirement.title}`);
+      // Logic to display requirement details in the main content area
+    };
+
+    const addNewRequirement = () => {
+      console.log('Adding new requirement...');
+      // Logic to add a new requirement
+    };
+
+    const toggleSidebar = () => {
+      console.log('Toggling sidebar...');
+      // Logic to toggle the visibility of the sidebar
+    };
+
+    const selectExpandedRequirement = (requirement) => {
+      console.log(`Selected expanded requirement: ${requirement.title}`);
+      // Logic to display expanded requirement details in the main content area
+    };
+
+    const isSidebarExpanded = ref(true);
+
+    return {
+      requirements,
+      expandedRequirements,
+      selectRequirement,
+      addNewRequirement,
+      toggleSidebar,
+      selectExpandedRequirement,
+      isSidebarExpanded,
+    };
+  },
+};
+</script>
+
+<style scoped>
+.sidebar-container {
+  width: 250px;
+  height: 100%;
+  background-color: #08002E;
+  color: white;
+  position: fixed;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  overflow-y: auto;
+  padding: 20px;
+  transition: transform 0.3s ease-in-out;
+}
+
+.fixed-requirements {
+  margin-bottom: 20px;
+}
+
+.requirements-list {
+  margin-bottom: 20px;
+}
+
+.requirements-list h2 {
+  margin-bottom: 10px;
+}
+
+.requirements-list ul {
+  list-style: none;
+  padding: 0;
+}
+
+.requirements-list li {
+  cursor: pointer;
+  padding: 10px;
+  border-radius: 5px;
+  background-color: #1E1E1E;
+  margin-bottom: 10px;
+  transition: background-color 0.3s ease-in-out;
+}
+
+.requirements-list li:hover {
+  background-color: #2E2E2E;
+}
+
+.add-new-requirement-button {
+  width: 100%;
+  padding: 10px;
+  background-color: #1E1E1E;
+  color: white;
+  border: none;
+  cursor: pointer;
+  border-radius: 5px;
+  margin-bottom: 20px;
+  transition: background-color 0.3s ease-in-out;
+}
+
+.add-new-requirement-button:hover {
+  background-color: #2E2E2E;
+}
+
+.toggle-sidebar-button {
+  position: absolute;
+  top: 20px;
+  right: -40px;
+  background-color: #1E1E1E;
+  color: white;
+  border: none;
+  cursor: pointer;
+  border-radius: 50%;
+  padding: 10px;
+  transition: transform 0.3s ease-in-out;
+}
+
+.toggle-sidebar-button:hover {
+  transform: rotate(180deg);
+}
+
+.expanded-sidebar {
+  position: absolute;
+  top: 0;
+  left: 250px;
+  width: 250px;
+  height: 100%;
+  background-color: #08002E;
+  color: white;
+  position: fixed;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  overflow-y: auto;
+  padding: 20px;
+  transition: transform 0.3s ease-in-out;
+}
+
+.expanded-requirements {
+  margin-bottom: 20px;
+}
+
+.expanded-requirements h2 {
+  margin-bottom: 10px;
+}
+
+.expanded-requirements ul {
+  list-style: none;
+  padding: 0;
+}
+
+.expanded-requirements li {
+  cursor: pointer;
+  padding: 10px;
+  border-radius: 5px;
+  background-color: #1E1E1E;
+  margin-bottom: 10px;
+  transition: background-color 0.3s ease-in-out;
+}
+
+.expanded-requirements li:hover {
+  background-color: #2E2E2E;
+}
+
+.slide-enter-active, .slide-leave-active {
+  transition: all 0.3s ease;
+}
+.slide-enter, .slide-leave-to {
+  transform: translateX(-250px);
+  opacity: 0;
+}
+</style>

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä