Skip to content

Commit 845c1e3

Browse files
h0842398z423gLeonFraschtgeilen
authored
Initial Frontend (#19)
* basic implementation of frontend * Updated Main / Start page and Login Mechanism * Updated search results to be scrollable while keeping the first row fixed in ResultsSection.vue AND made the InputSection.vue correctly scrollable (only the part of this container shall be scrollable, not the whole screen with the toolbar) * Remove backend/package.json * Remove backend/package-lock.json --------- Co-authored-by: ge87pot <ge87pot@tum.de> Co-authored-by: Tobias Geilen <63714365+tgeilen@users.noreply.github.com>
1 parent 3cc8dc1 commit 845c1e3

8 files changed

Lines changed: 584 additions & 6 deletions

File tree

frontend/package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
},
2424
"dependencies": {
2525
"axios": "^1.13.1",
26+
"lucide-vue-next": "^0.554.0",
2627
"pinia": "^3.0.3",
2728
"tailwindcss": "^4.1.16",
2829
"vue": "^3.5.22",

frontend/src/components/HomeView.vue

Lines changed: 189 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,192 @@
11
<script setup lang="ts">
2+
import { ref } from 'vue';
3+
import { VLayout, VAppBar, VNavigationDrawer, VMain, VBtn, VIcon, VToolbarTitle, VContainer } from 'vuetify/components';
4+
import { Menu as MenuIcon, FileText } from 'lucide-vue-next'; // Lucide Icons
5+
import Sidebar from './Sidebar.vue';
6+
import InputSection from './InputSection.vue';
7+
import ResultsSection from './ResultsSection.vue';
8+
import { Paper, Project } from './types'; // Importiere die Typen
9+
10+
import { useAuthStore } from '@/stores/auth';
11+
import { login } from '@/services/auth';
12+
import {AxiosError} from "axios";
13+
14+
// Zustand
15+
const sidebarOpen = ref(false);
16+
const currentQuery = ref<string | null>(null);
17+
const outputs = ref<Paper[]>([]);
18+
//const isLoggedIn = ref(false);
19+
20+
const errorMessage = ref<string | null>(null);
21+
const isLoading = ref(false);
22+
const authStore = useAuthStore();
23+
24+
const initialProjects: Project[] = [
25+
{
26+
id: '1',
27+
name: 'Project Alpha',
28+
query: 'Machine learning applications in healthcare',
29+
date: '2025-11-15',
30+
outputs: [
31+
{ title: 'Deep Learning for Medical Image Analysis', author: 'Smith, J. et al.', year: 2024, url: 'https://example.com/paper1' },
32+
{ title: 'AI-Driven Diagnosis Systems', author: 'Johnson, M. & Lee, K.', year: 2023, url: 'https://example.com/paper2' }
33+
]
34+
},
35+
{
36+
id: '2',
37+
name: 'Project Beta',
38+
query: 'Climate change impacts on biodiversity',
39+
date: '2025-11-14',
40+
outputs: [
41+
{ title: 'Global Warming Effects on Ecosystems', author: 'Brown, A. et al.', year: 2024, url: 'https://example.com/paper3' }
42+
]
43+
},
44+
{
45+
id: '3',
46+
name: 'Project Gamma',
47+
query: 'Quantum computing advances',
48+
date: '2025-11-13',
49+
outputs: [
50+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
51+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
52+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
53+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
54+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
55+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
56+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
57+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
58+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
59+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
60+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
61+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
62+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
63+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' },
64+
{ title: 'Quantum Algorithms for Optimization', author: 'Chen, L. & Wang, Y.', year: 2023, url: 'https://example.com/paper4' }
65+
]
66+
}
67+
];
68+
const recentProjects = ref<Project[]>(initialProjects);
69+
70+
// Methoden
71+
const handleSubmitQuery = (query: string) => {
72+
currentQuery.value = query;
73+
74+
// Simuliere die Generierung von Artikeln
75+
const generatedOutputs: Paper[] = [
76+
{ title: 'Recent Advances in Natural Language Processing', author: 'Anderson, P. & Martinez, R.', year: 2024, url: 'https://example.com/nlp-advances' },
77+
{ title: 'Transformer Models: A Comprehensive Review', author: 'Davis, K. et al.', year: 2023, url: 'https://example.com/transformers' },
78+
{ title: 'Attention Mechanisms in Neural Networks', author: 'Wilson, T. & Thompson, S.', year: 2024, url: 'https://example.com/attention' },
79+
{ title: 'BERT and Beyond: Language Model Evolution', author: 'Garcia, M. et al.', year: 2023, url: 'https://example.com/bert' },
80+
{ title: 'Large Language Models in Practice', author: 'Taylor, J. & White, L.', year: 2024, url: 'https://example.com/llm-practice' }
81+
];
82+
outputs.value = generatedOutputs;
83+
84+
// Füge zu den aktuellen Projekten hinzu
85+
const newProject: Project = {
86+
id: Date.now().toString(),
87+
name: `Project ${recentProjects.value.length + 1}`,
88+
query,
89+
date: new Date().toISOString().split('T')[0],
90+
outputs: generatedOutputs
91+
};
92+
recentProjects.value.unshift(newProject); // Füge am Anfang hinzu
93+
};
94+
95+
const handleProjectSelect = (project: Project) => {
96+
currentQuery.value = project.query;
97+
outputs.value = project.outputs;
98+
sidebarOpen.value = false;
99+
};
100+
101+
const handleNewQuery = () => {
102+
currentQuery.value = null;
103+
outputs.value = [];
104+
};
105+
/*
106+
const handleLogin = (email: string, password: string) => {
107+
// Mock login logic
108+
isLoggedIn.value = true;
109+
sidebarOpen.value = false;
110+
console.log(`Logging in with: ${email} and ${password}`);
111+
};
112+
*/
113+
const handleLogin = async (usernameFromSidebar: string) => {
114+
isLoading.value = true;
115+
errorMessage.value = null;
116+
117+
try {
118+
const { access_token, refresh_token, user } = await login(usernameFromSidebar);
119+
120+
authStore.setAuth({
121+
accessToken: access_token,
122+
refreshToken: refresh_token,
123+
user: user,
124+
});
125+
sidebarOpen.value = false;
126+
} catch (error: unknown) {
127+
const axiosError = error as AxiosError<{ detail?: string }>;
128+
129+
if (axiosError.response?.data?.detail) {
130+
errorMessage.value = axiosError.response.data.detail;
131+
} else {
132+
errorMessage.value = 'An unexpected error occurred.';
133+
}
134+
} finally {
135+
isLoading.value = false;
136+
}
137+
}
138+
const handleLogout = () => {
139+
//isLoggedIn.value = false;
140+
authStore.clearAuth();
141+
};
142+
</script>
143+
144+
<template>
145+
<v-app>
146+
<v-layout>
147+
<v-navigation-drawer
148+
v-model="sidebarOpen"
149+
location="left"
150+
temporary
151+
width="320"
152+
>
153+
<Sidebar
154+
:is-open="sidebarOpen"
155+
:recent-projects="recentProjects"
156+
:is-logged-in="authStore.isAuthenticated"
157+
@close="sidebarOpen = false"
158+
@project-select="handleProjectSelect"
159+
@new-project="handleNewQuery"
160+
@login="handleLogin"
161+
@logout="handleLogout"
162+
/>
163+
</v-navigation-drawer>
164+
165+
<v-app-bar app color="white" flat border>
166+
<v-btn icon variant="text" @click="sidebarOpen = !sidebarOpen">
167+
<v-icon :icon="MenuIcon" />
168+
</v-btn>
169+
<v-toolbar-title class="text-h6">AI Text Processor</v-toolbar-title>
170+
<v-spacer></v-spacer>
171+
<v-btn v-if="currentQuery" @click="handleNewQuery" variant="outlined" color="primary">
172+
Neue Abfrage
173+
</v-btn>
174+
</v-app-bar>
175+
176+
<v-main class="bg-grey-lighten-4">
177+
<v-container fluid class="h-100">
178+
<div v-if="!currentQuery">
179+
<InputSection @submit="handleSubmitQuery" />
180+
</div>
181+
<div v-else>
182+
<ResultsSection :query="currentQuery" :outputs="outputs" />
183+
</div>
184+
</v-container>
185+
</v-main>
186+
</v-layout>
187+
</v-app>
188+
</template>
189+
<!--<script setup lang="ts">
2190
import { useAuthStore } from '@/stores/auth';
3191
4192
const authStore = useAuthStore();
@@ -9,4 +197,4 @@ const authStore = useAuthStore();
9197
<p>{{ authStore.accessToken }}</p>
10198
</template>
11199
12-
<style scoped></style>
200+
<style scoped></style>-->
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue';
3+
import { VCard, VCardTitle, VCardText, VTextarea, VBtn, VIcon, VRow, VCol } from 'vuetify/components';
4+
import { Send } from 'lucide-vue-next';
5+
6+
const emit = defineEmits(['submit']);
7+
8+
const input = ref('');
9+
10+
const handleSubmit = () => {
11+
if (input.value.trim()) {
12+
emit('submit', input.value);
13+
input.value = '';
14+
}
15+
};
16+
</script>
17+
18+
<template>
19+
<div class="input-wrapper">
20+
<v-container fluid class="fill-height align-center justify-center">
21+
<div class="w-100" style="max-width: 900px;">
22+
<div class="text-center mb-10">
23+
<h2 class="text-h4 mb-2">Willkommen beim AI Text Processor</h2>
24+
<p class="text-medium-emphasis">
25+
Geben Sie Ihre Texteingabe unten ein und lassen Sie unsere KI leistungsstarke Ergebnisse für Sie generieren
26+
</p>
27+
</div>
28+
29+
<v-form @submit.prevent="handleSubmit">
30+
<v-textarea
31+
v-model="input"
32+
label="Geben Sie Ihren Text hier ein..."
33+
variant="outlined"
34+
auto-grow
35+
rows="8"
36+
class="mb-4"
37+
></v-textarea>
38+
<v-btn
39+
type="submit"
40+
color="primary"
41+
block
42+
size="large"
43+
:disabled="!input.trim()"
44+
>
45+
<v-icon :icon="Send" start></v-icon>
46+
Ergebnis generieren
47+
</v-btn>
48+
</v-form>
49+
50+
<v-row class="mt-12">
51+
<v-col cols="12" md="4">
52+
<v-card flat class="pa-4 text-center border-sm">
53+
<div class="d-flex align-center justify-center mx-auto mb-4 bg-blue-lighten-4 rounded-circle" style="width: 48px; height: 48px;">
54+
<span class="text-blue-darken-2 text-h6">1</span>
55+
</div>
56+
<v-card-title class="text-h6 mb-2 pa-0">Eingabe</v-card-title>
57+
<v-card-text class="text-medium-emphasis pa-0 text-body-2">
58+
Geben Sie Ihre Textabfrage oder Anfrage ein
59+
</v-card-text>
60+
</v-card>
61+
</v-col>
62+
<v-col cols="12" md="4">
63+
<v-card flat class="pa-4 text-center border-sm">
64+
<div class="d-flex align-center justify-center mx-auto mb-4 bg-blue-lighten-4 rounded-circle" style="width: 48px; height: 48px;">
65+
<span class="text-blue-darken-2 text-h6">2</span>
66+
</div>
67+
<v-card-title class="text-h6 mb-2 pa-0">KI-Verarbeitung</v-card-title>
68+
<v-card-text class="text-medium-emphasis pa-0 text-body-2">
69+
Unsere KI wertet Ihre Eingabe aus und verarbeitet sie
70+
</v-card-text>
71+
</v-card>
72+
</v-col>
73+
<v-col cols="12" md="4">
74+
<v-card flat class="pa-4 text-center border-sm">
75+
<div class="d-flex align-center justify-center mx-auto mb-4 bg-blue-lighten-4 rounded-circle" style="width: 48px; height: 48px;">
76+
<span class="text-blue-darken-2 text-h6">3</span>
77+
</div>
78+
<v-card-title class="text-h6 mb-2 pa-0">Ergebnisse</v-card-title>
79+
<v-card-text class="text-medium-emphasis pa-0 text-body-2">
80+
Erhalten Sie organisierte Ergebnisordner
81+
</v-card-text>
82+
</v-card>
83+
</v-col>
84+
</v-row>
85+
</div>
86+
</v-container>
87+
</div>
88+
89+
</template>
90+
91+
<style scoped>
92+
/* Vuetify-Klassen werden bevorzugt, aber einige benutzerdefinierte Stile für die Kreise */
93+
.bg-blue-lighten-4 {
94+
background-color: #E3F2FD !important; /* Vuetify's light blue */
95+
}
96+
.text-blue-darken-2 {
97+
color: #1976D2 !important; /* Vuetify's darker blue */
98+
}
99+
.border-sm {
100+
border: 1px solid #E0E0E0; /* Light border similar to tailwind's gray-200 */
101+
}
102+
.input-wrapper {
103+
max-height: 85vh;
104+
overflow-y: auto;
105+
padding-right: 6px;
106+
}
107+
108+
</style>

0 commit comments

Comments
 (0)