@@ -0,0 +1,30 @@ | |||
<?php | |||
namespace eindwerk\Controller; | |||
use eindwerk\Entity\Team; | |||
use Psr\Http\Message\ResponseInterface as Response; | |||
use Psr\Http\Message\ServerRequestInterface as Request; | |||
use Psr\Container\ContainerInterface; | |||
class TeamsController | |||
{ | |||
protected $container; | |||
protected $response; | |||
public function __construct(ContainerInterface $container) | |||
{ | |||
$this->container = $container; | |||
} | |||
function getTeams(Request $request, Response $response, array $args) | |||
{ | |||
$task = new Team($this->container); | |||
$data = $task->getTeams(); | |||
$response->getBody()->write(json_encode($data)); | |||
return $response->withHeader('Content-Type', 'application/json'); | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
<?php | |||
namespace eindwerk\Entity; | |||
use Psr\Container\ContainerInterface; | |||
class Team | |||
{ | |||
protected $container; | |||
public function __construct(ContainerInterface $container) | |||
{ | |||
$this->container = $container; | |||
} | |||
public function getTeams(): array | |||
{ | |||
$db = $this->container->get('db'); | |||
$query = $db->prepare(' | |||
SELECT T.id, T.name | |||
FROM team T | |||
ORDER BY name asc | |||
'); | |||
$res = $query->execute(); | |||
$data = []; | |||
while ($row = $res->fetchArray(SQLITE3_ASSOC)) { | |||
array_push($data, $row); | |||
} | |||
return $data; | |||
} | |||
} |
@@ -69,6 +69,7 @@ $app->group('/api', function (RouteCollectorProxy $group) { | |||
$group->options('/assignUserToCard', PreflightAction::class); | |||
$group->options('/tasksGet', PreflightAction::class); | |||
$group->options('/deleteTask', PreflightAction::class); | |||
$group->options('/teams', PreflightAction::class); | |||
}); | |||
$app->group('/api', function (RouteCollectorProxy $group) { | |||
@@ -91,6 +92,7 @@ $app->group('/api', function (RouteCollectorProxy $group) { | |||
$group->post('/assignUserToCard', ProjectsController::class . ':assignUserToCard'); | |||
$group->post('/tasksGet', ProjectsController::class . ':getTasks'); | |||
$group->post('/deleteTask', ProjectsController::class . ':deleteTask'); | |||
$group->post('/teams', TeamsController::class . ':getTeams'); | |||
})->add(AuthMiddleware::class); | |||
// Add Routing Middleware |
@@ -13,3 +13,4 @@ Optional: set DB_FILE environment variable | |||
```sh | |||
php faker.php | |||
``` | |||
php |
@@ -2,7 +2,7 @@ | |||
require __DIR__ . '/vendor/autoload.php'; | |||
$dbfile = getenv("DB_FILE") ?: "database.sqlite"; | |||
$dbfile = getenv("DB_FILE") ?: "db2.sqlite"; | |||
$db = new SQLite3('../../backend/db/' . $dbfile); | |||
$faker = Faker\Factory::create(); |
@@ -1,71 +0,0 @@ | |||
<template> | |||
<div class="container"> | |||
<h1>Teams</h1> | |||
<table class="teams"> | |||
<thead> | |||
<tr> | |||
<th>Name</th> | |||
<th>Description</th> | |||
<th>Users</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr class="table-style"> | |||
<td>test</td> | |||
<td>test</td> | |||
<td>test</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
layout: 'nav&foot', | |||
}; | |||
</script> | |||
<style lang="scss"> | |||
.container { | |||
margin: 0 auto; | |||
min-height: 93.5vh; | |||
display: flex; | |||
background-color: #f5f9fa; | |||
} | |||
.title { | |||
font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont, | |||
'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; | |||
display: block; | |||
font-weight: 300; | |||
font-size: 100px; | |||
color: #35495e; | |||
letter-spacing: 1px; | |||
} | |||
.subtitle { | |||
font-weight: 300; | |||
font-size: 42px; | |||
color: #526488; | |||
word-spacing: 5px; | |||
padding-bottom: 15px; | |||
} | |||
.links { | |||
padding-top: 15px; | |||
} | |||
table.teams { | |||
font-size: 20px; | |||
line-height: 24px; | |||
width: 50%; | |||
} | |||
th { | |||
color: #8a8a8a; | |||
} | |||
td { | |||
} | |||
</style> |
@@ -0,0 +1,83 @@ | |||
<template> | |||
<div class="container"> | |||
<div v-if="!loading"> | |||
<FormulateForm @submit="saveProject($event, project.id)"> | |||
<FormulateInput type="hidden" name="id" :value="project.id" /> | |||
<FormulateInput | |||
type="text" | |||
name="name" | |||
:value="project.name" | |||
label="Name" | |||
/> | |||
<FormulateInput | |||
type="textarea" | |||
name="description" | |||
:value="project.description" | |||
label="Description" | |||
/> | |||
<FormulateInput type="hidden" name="team_id" :value="project.team_id" /> | |||
<FormulateInput | |||
type="text" | |||
name="team_name" | |||
:value="project.team_name" | |||
label="Team" | |||
disabled="true" | |||
/> | |||
<FormulateInput | |||
type="hidden" | |||
name="client_id" | |||
:value="project.client_id" | |||
/> | |||
<FormulateInput | |||
type="text" | |||
name="client_name" | |||
:value="project.client_name" | |||
label="Client" | |||
disabled="true" | |||
/> | |||
<FormulateInput type="submit" value="save" label="Save" /> | |||
</FormulateForm> | |||
<n-link :to="'/factuur/new?project=' + project.id"> | |||
factureer | |||
</n-link> | |||
</div> | |||
<Loader /> | |||
</div> | |||
</template> | |||
<script> | |||
import { mapState, mapActions } from 'vuex'; | |||
import Loader from '~/components/Loader'; | |||
export default { | |||
components: { Loader }, | |||
data() { | |||
return { | |||
id: Number(this.$route.params.id), | |||
}; | |||
}, | |||
layout: 'nav&foot', | |||
computed: { | |||
...mapState({ | |||
project: (state) => state.projects.currentProject, | |||
loading: 'loading', | |||
}), | |||
}, | |||
mounted() { | |||
this.fetchProject(this.id); | |||
}, | |||
methods: { | |||
...mapActions({ | |||
fetchProject: 'projects/fetchProject', | |||
saveProject: 'projects/saveProject', | |||
}), | |||
}, | |||
}; | |||
</script> | |||
<style> | |||
textarea { | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,84 @@ | |||
<template> | |||
<div class="container projects"> | |||
<n-link to="/teams/new" class="button-teams"> | |||
Create new project | |||
</n-link> | |||
<div> | |||
<input v-model="search" type="text" placeholder="search team ..." /> | |||
</div> | |||
<div> | |||
<table> | |||
<thead> | |||
<tr> | |||
<th> | |||
name | |||
</th> | |||
</tr> | |||
</thead> | |||
<tbody v-if="!loading && !search"> | |||
<tr v-for="team in teams" :key="team.id"> | |||
<td>{{ team.name }}</td> | |||
<td> | |||
<n-link :to="'/teams/' + team.id"> | |||
meer info | |||
</n-link> | |||
</td> | |||
</tr> | |||
</tbody> | |||
<Loader /> | |||
</table> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { mapState, mapActions } from 'vuex'; | |||
import Loader from '~/components/Loader'; | |||
export default { | |||
components: { Loader }, | |||
data() { | |||
return { | |||
filterTimeout: null, | |||
search: '', | |||
filteredProjects: [], | |||
}; | |||
}, | |||
layout: 'nav&foot', | |||
computed: { | |||
...mapState({ | |||
projects: (state) => state.teams.list, | |||
loading: 'loading', | |||
}), | |||
}, | |||
watch: { | |||
// search(val) { | |||
// this.filteredProjects = this.projects.filter( | |||
// (project) => | |||
// project.description.toLowerCase().includes(val.toLowerCase()) || | |||
// project.name.toLowerCase().includes(val.toLowerCase()), | |||
// ); | |||
// }, | |||
}, // | |||
mounted() { | |||
if (this.teams.length === 0) this.fetchAllProjects(); | |||
}, | |||
methods: { | |||
...mapActions({ fetchAllTeams: 'teams/fetchAllTeams' }), | |||
}, | |||
}; | |||
</script> | |||
<style> | |||
.container.projects { | |||
flex-flow: column; | |||
} | |||
.button-projects { | |||
margin: 8px 0; | |||
padding: 12px 20px; | |||
box-sizing: border-box; | |||
border: 2px solid black; | |||
border-radius: 8px; | |||
font-weight: bold; | |||
background-image: linear-gradient(to top right, #e1e4e5, #f5f9fa); | |||
} | |||
</style> |
@@ -0,0 +1,31 @@ | |||
<template> | |||
<div class="container"> | |||
<FormulateForm @submit="saveProject"> | |||
<FormulateInput | |||
type="text" | |||
name="name" | |||
label="Name" | |||
placeholder="name" | |||
validation="required" | |||
/> | |||
<FormulateInput | |||
type="textarea" | |||
name="description" | |||
label="Description" | |||
placeholder="description" | |||
validation="required" | |||
/> | |||
<FormulateInput type="submit" label="Create" /> | |||
</FormulateForm> | |||
</div> | |||
</template> | |||
<script> | |||
import { mapActions } from 'vuex'; | |||
export default { | |||
layout: 'nav&foot', | |||
methods: { | |||
...mapActions({ saveProject: 'projects/saveProject' }), | |||
}, | |||
}; | |||
</script> |
@@ -0,0 +1,24 @@ | |||
export const state = () => ({ | |||
list: [], | |||
}); | |||
export const getters = {}; | |||
export const mutations = { | |||
setTeams(state, teams) { | |||
state.list = teams; | |||
}, | |||
}; | |||
export const actions = { | |||
fetchAllTeams({ commit }) { | |||
commit('setLoading', true, { root: true }); | |||
this.$axios | |||
.get('/teams') | |||
.then((res) => { | |||
commit('setTeams', res.data); | |||
commit('setLoading', true, { root: true }); | |||
}) | |||
.catch((error) => console.error(error)); | |||
}, | |||
}; |