frontend of sidebar
This commit is contained in:
parent
84aa9b3e22
commit
18c94bd7a0
|
@ -4,6 +4,7 @@
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="/img/favicon.png" />
|
<link rel="icon" href="/img/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/index.css" />
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover">
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<script lang="ts">
|
||||||
|
export const projectId: number = 0;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if Number.isNaN(projectId)}
|
||||||
|
<p>Invalid number</p>
|
||||||
|
{:else}
|
||||||
|
<p>Hello on dashboard {projectId}!</p>
|
||||||
|
{/if}
|
|
@ -0,0 +1,82 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { projects } from "../stores/projects";
|
||||||
|
|
||||||
|
let newProject = false;
|
||||||
|
let editProject: number | undefined = undefined;
|
||||||
|
|
||||||
|
function handleKeydown(event: KeyboardEvent, id: number | undefined = undefined) {
|
||||||
|
if (event.key === 'Enter' && event.target) {
|
||||||
|
if(id !== undefined){
|
||||||
|
projects.edit({
|
||||||
|
id: id,
|
||||||
|
title: (event.target as HTMLInputElement).value
|
||||||
|
})
|
||||||
|
editProject = undefined;
|
||||||
|
} else {
|
||||||
|
createNewProject((event.target as HTMLInputElement).value);
|
||||||
|
newProject = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNewProject(value: string) {
|
||||||
|
projects.add({
|
||||||
|
title: value,
|
||||||
|
id: undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/sidebar.css" />
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<div id="sidebar" class="sidebar">
|
||||||
|
<div class="logo">
|
||||||
|
<a href="/">
|
||||||
|
<img src="img/icon.svg" alt="">
|
||||||
|
<span class="title">Focus</span>
|
||||||
|
<span class="version">v0.0.1</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="boards">
|
||||||
|
{#await projects.init()}
|
||||||
|
<p>Loading ...</p>
|
||||||
|
{:then}
|
||||||
|
<h2>Projects</h2>
|
||||||
|
<ul>
|
||||||
|
{#each $projects as project}
|
||||||
|
<li>
|
||||||
|
{#if editProject === project.id}
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
on:keydown={(e) => handleKeydown(e, project.id)}
|
||||||
|
value={project.title}
|
||||||
|
class="edit-input"
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<a href="/{project.id}">{project.title}</a><span class="edit-icon" on:click={() => editProject = project.id}>️
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="18" viewBox="0 0 576 512"><path d="M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z" fill="#aaa"/></svg>
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
{#if newProject}
|
||||||
|
<li>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Enter project title"
|
||||||
|
on:keydown={handleKeydown}
|
||||||
|
style="padding: 8px; border: 1px solid #ccc; border-radius: 4px; width: 100%;" />
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
|
</ul>
|
||||||
|
{:catch error}
|
||||||
|
<p>Something went wrong: {error.message}</p>
|
||||||
|
{/await}
|
||||||
|
</div>
|
||||||
|
<div class="bottom-links">
|
||||||
|
<span on:click={() => newProject = true}>New project</span>
|
||||||
|
<span>Settings</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,33 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { projects } from "../stores/projects";
|
import Sidebar from "../components/sidebar.svelte";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<Sidebar />
|
||||||
<link rel="stylesheet" type="text/css" href="/css/index.css" />
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
{#await projects.init()}
|
|
||||||
<p>Loading ...</p>
|
|
||||||
{:then}
|
|
||||||
<div id="sidebar" class="sidebar">
|
|
||||||
<div class="logo">
|
|
||||||
<img src="img/icon.svg" alt="">
|
|
||||||
<span class="title">Focus</span>
|
|
||||||
<span class="version">v0.0.1</span>
|
|
||||||
</div>
|
|
||||||
<div class="boards">
|
|
||||||
<h2>Projects</h2>
|
|
||||||
<ul>
|
|
||||||
{#each $projects as project}
|
|
||||||
<!-- <li><a href="/{{project.id}}">{{project.title}}</a></li> -->
|
|
||||||
{/each}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="bottom-links">
|
|
||||||
<a href="#">Add board</a>
|
|
||||||
<a href="#">Settings</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{:catch error}
|
|
||||||
<p>Something went wrong: {error.message}</p>
|
|
||||||
{/await}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import Project from "../../components/project.svelte";
|
||||||
|
import Sidebar from "../../components/sidebar.svelte";
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
|
let projectId: number = +$page.params.project;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Sidebar />
|
||||||
|
<Project {projectId} />
|
|
@ -6,23 +6,51 @@ export const projects = getProjects();
|
||||||
const backend = 'http://127.0.0.1:3000'
|
const backend = 'http://127.0.0.1:3000'
|
||||||
|
|
||||||
interface Project {
|
interface Project {
|
||||||
id: number,
|
id: number | undefined,
|
||||||
title: string,
|
title: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProjects() {
|
function getProjects() {
|
||||||
const { subscribe, set, update } = writable([]);
|
const { subscribe, set, update } = writable([] as Project[]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
init: async () => {
|
init: async () => {
|
||||||
const response = await axios.get(`${backend}/api/projects`)
|
const response = await axios.get(`${backend}/api/projects`);
|
||||||
console.log(response.data)
|
|
||||||
|
|
||||||
if(response.status < 303) {
|
if(response.status < 303) {
|
||||||
const projects: Project[] = response.data;
|
const data: Project[] = response.data;
|
||||||
|
|
||||||
return projects;
|
set(data);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
add: async (project: Project) => {
|
||||||
|
const response = await axios.post(`${backend}/api/project`, project);
|
||||||
|
|
||||||
|
if(response.status < 303) {
|
||||||
|
project.id = response.data["id"];
|
||||||
|
update((oldProjects) => {
|
||||||
|
oldProjects.push(project)
|
||||||
|
return oldProjects;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
edit: async (project: Project) => {
|
||||||
|
const response = await axios.put(`${backend}/api/project/${project.id}`, project)
|
||||||
|
|
||||||
|
|
||||||
|
if(response.status < 303) {
|
||||||
|
update((oldProjects: Project[]) => {
|
||||||
|
for(let p of oldProjects){
|
||||||
|
if(p.id === project.id){
|
||||||
|
p.title = project.title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldProjects;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,71 +3,6 @@ body {
|
||||||
font-family: "Open sans", sans-serif;
|
font-family: "Open sans", sans-serif;
|
||||||
color: white;
|
color: white;
|
||||||
background-color: #2b2e30;
|
background-color: #2b2e30;
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar {
|
|
||||||
width: 240px;
|
|
||||||
background-color: #262a2b;
|
|
||||||
color: white;
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .logo {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .logo img {
|
|
||||||
max-height: 30px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .logo .title {
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
#sidebar .logo .version {
|
|
||||||
font-size: 0.8em;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .boards h2 {
|
|
||||||
padding-left: 10px;
|
|
||||||
font-size: 0.9em;
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .boards ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
padding: 0;
|
||||||
|
}
|
||||||
#sidebar .boards ul li a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: white;
|
|
||||||
display: block;
|
|
||||||
padding: 5px 10px;
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .boards ul li a:hover {
|
|
||||||
background-color: #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .bottom-links {
|
|
||||||
margin-top: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar .bottom-links a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: white;
|
|
||||||
display: block;
|
|
||||||
padding: 10px;
|
|
||||||
font-size: 0.9em;
|
|
||||||
border-top: 1px solid #444;
|
|
||||||
}
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
#sidebar {
|
||||||
|
width: 240px;
|
||||||
|
background-color: #262a2b;
|
||||||
|
color: white;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .logo img {
|
||||||
|
max-height: 30px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .logo .title {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
#sidebar .logo .version {
|
||||||
|
font-size: 0.8em;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .boards h2 {
|
||||||
|
padding-left: 10px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .boards ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .boards ul li:hover {
|
||||||
|
background-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .bottom-links {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .bottom-links span {
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
display: block;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
border-top: 1px solid #444;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar li {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .edit-icon {
|
||||||
|
visibility: hidden;
|
||||||
|
margin-right: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar li:hover .edit-icon {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
Loading…
Reference in New Issue