Skip to content
Extraits de code Groupes Projets
Valider 5d218822 rédigé par Brieuc Dubois's avatar Brieuc Dubois
Parcourir les fichiers

Update home page look

parent a7198cd1
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!6Feat/homepage ux
......@@ -77,12 +77,20 @@ def create_user_survey_weekly(db: Session, user_id: int, survey: schemas.SurveyC
def get_contact_sessions(db: Session, user_id: int, contact_id: int):
return (
sessions = (
db.query(models.Session)
.filter(models.Session.users.any(models.User.id == user_id))
.filter(models.Session.users.any(models.User.id == contact_id))
.all()
)
for session in sessions:
session.length = (
db.query(models.Message)
.filter(models.Message.session_id == session.id)
.count()
)
return sessions
def create_session(db: Session, user: schemas.User):
......
......@@ -22,10 +22,7 @@
"history": "Historique"
},
"home": {
"date": "Date",
"participants": "Participants",
"email": "E-mail",
"actions": "Actions",
"add": "Ajouter",
"deleteSessionConfirm": "Êtes-vous sûr de vouloir supprimer cette session ? Cette action est irréversible.",
"createSession": "Session immédiate",
......@@ -42,7 +39,9 @@
"pastSessions": "Sessions terminées",
"newContact": "Ajouter un contact",
"bookingSuccessful": "Session réservée avec succès",
"bookingFailed": "Erreur lors de la réservation de la session"
"bookingFailed": "Erreur lors de la réservation de la session",
"noCurrentOrFutureSessions": "Aucune session en cours ou planifiée",
"noSessions": "Aucune session"
},
"login": {
"email": "E-mail",
......@@ -286,6 +285,20 @@
"november": "novembre",
"december": "décembre"
},
"shortMonth": {
"january": "janv.",
"february": "févr.",
"march": "mars",
"april": "avr.",
"may": "mai",
"june": "juin",
"july": "juil.",
"august": "août",
"september": "sept.",
"october": "oct.",
"november": "nov.",
"december": "déc."
},
"days": {
"monday": "Lundi",
"tuesday": "Mardi",
......@@ -324,7 +337,13 @@
"words": {
"date": "Date",
"messages": "Messages",
"actions": "Actions"
"actions": "Actions",
"participants": "Participants",
"status": "Statut",
"date": "Date",
"programed": "Programmée",
"inProgress": "En cours",
"finished": "Terminée"
}
},
"inputs": {
......
......@@ -32,6 +32,37 @@ export function getFullMonth(id: number): string {
}
}
export function getShortMonth(id: number): string {
switch (id) {
case 0:
return get(t)('utils.shortMonth.january');
case 1:
return get(t)('utils.shortMonth.february');
case 2:
return get(t)('utils.shortMonth.march');
case 3:
return get(t)('utils.shortMonth.april');
case 4:
return get(t)('utils.shortMonth.may');
case 5:
return get(t)('utils.shortMonth.june');
case 6:
return get(t)('utils.shortMonth.july');
case 7:
return get(t)('utils.shortMonth.august');
case 8:
return get(t)('utils.shortMonth.september');
case 9:
return get(t)('utils.shortMonth.october');
case 10:
return get(t)('utils.shortMonth.november');
case 11:
return get(t)('utils.shortMonth.december');
default:
return '??';
}
}
export function displayDate(date: Date): string {
if (date === null) return '';
......@@ -110,16 +141,16 @@ export function formatToUTCDate(date: Date): string {
}
export function displayShortTime(date: Date): string {
const now = new Date();
return (
('0' + date.getDate()).slice(-2) +
'/' +
('0' + (date.getMonth() + 1)).slice(-2) +
'/' +
date.getFullYear() +
' ' +
getShortMonth(date.getMonth()) +
(date.getFullYear() != now.getFullYear() ? ' ' + date.getFullYear() : '') +
' ' +
('0' + date.getHours()).slice(-2) +
':' +
('0' + date.getMinutes()).slice(-2)
'h'
);
}
......
<script lang="ts">
import Session from '$lib/types/session';
import { onMount } from 'svelte';
import { displayShortTime, displayTime, displayTimeSince } from '$lib/utils/date';
import { displayShortTime, displayTimeSince } from '$lib/utils/date';
import {
AcademicCap,
Sparkles,
Icon,
User as UserIcon,
MagnifyingGlass,
ArrowRight,
ArrowRightCircle
} from 'svelte-hero-icons';
import { t } from '$lib/services/i18n';
......@@ -29,7 +28,10 @@
let modalNew = false;
let nickname = '';
let showTerminatedSessions = false;
async function selectContact(c: User | null) {
showTerminatedSessions = false;
contact = c;
if (!contact) {
contactSessions = [];
......@@ -138,87 +140,160 @@
}
</script>
<svelte:head>
<script>
</script>
</svelte:head>
{#if ready}
<div class="flex-col flex p-4 lg:w-[64rem] lg:mx-auto">
{#if contact}
<div>
<button on:click|preventDefault={createSession} class="button float-start mr-2">
{$t('home.createSession')}
</button>
<button
class="button float-start"
class:btn-disabled={!contact || !contact.calcom_link}
data-cal-link={`${contact.calcom_link}?email=${$user?.email}&name=${$user?.nickname}`}
>
{$t('home.bookSession')}
</button>
<div class="flex-row h-full flex py-4 flex-grow overflow-y-hidden">
<div class="flex flex-col border shadow-[0_0_6px_0_rgba(0,14,156,.2)] min-w-72 rounded-r-xl">
<div class="flex-grow">
{#each contacts as c (c.id)}
<div
class="h-24 flex border-gray-300 border-b-2 hover:bg-gray-200 hover:cursor-pointer p-4"
class:bg-gray-200={c.id === contact?.id}
on:click={() => selectContact(c)}
role="button"
aria-label={c.nickname}
tabindex="0"
on:keydown={(e) => e.key === 'Enter' && selectContact(c)}
>
<div class="w-16 ml-2 mr-4 p-4 bg-gray-300 rounded-2xl">
{#if c.type == 0}
<Icon src={Sparkles} class="mask mask-squircle" />
{:else if c.type == 1}
<Icon src={AcademicCap} class="" />
{:else}
<Icon src={UserIcon} />
{/if}
</div>
<div class="text-lg font-bold capitalize flex items-center">
{c.nickname}
</div>
</div>
{/each}
</div>
<div
class="border p-4 mt-4 rounded-xl shadow-[0_0_6px_0_rgba(0,14,156,.2)] overflow-y-scroll no-scrollbar"
<button
class="h-20 w-full flex justify-center items-center text-lg border-gray-200 border-t hover:bg-gray-200"
on:click={() => (modalNew = true)}
>
<table class="divide-y divide-neutral-300 text-center w-full">
<thead>
<tr>
<th scope="col" class="text-left">Date</th>
<th scope="col">Status</th>
<th scope="col">Participants</th>
<th scope="col"># messages</th>
<th scope="col"></th>
</tr>
</thead>
<tbody class="divide-y divide-neutral-200">
{#each contactSessions as s (s.id)}
+
</button>
</div>
{#if contact}
<div class="flex flex-col xl:mx-auto xl:w-[60rem] m-4">
<div>
<button on:click|preventDefault={createSession} class="button float-start mr-2">
{$t('home.createSession')}
</button>
<button
class="button float-start"
class:btn-disabled={!contact || !contact.calcom_link}
data-cal-link={`${contact.calcom_link}?email=${$user?.email}&name=${$user?.nickname}`}
>
{$t('home.bookSession')}
</button>
</div>
<div
class="border p-4 mt-4 rounded-xl shadow-[0_0_6px_0_rgba(0,14,156,.2)] overflow-y-scroll no-scrollbar"
>
<table class="divide-y divide-neutral-300 text-center w-full table-fixed">
<thead>
<tr>
<td class="py-2 text-left">
<div>
{displayShortTime(s.start_time)}
</div>
<div class="text-sm italic text-gray-600">
{displayTimeSince(s.start_time)}
</div>
</td>
<td class="py-2">
{#if s.start_time >= new Date(2024, 10, 13, 3) && s.start_time <= new Date()}
<span class="bg-purple-200 rounded-lg px-2 py-1">En ligne</span>
{:else if s.start_time <= new Date() && s.end_time >= new Date()}
<span class="bg-green-200 rounded-lg px-2 py-1">En cours</span>
{:else if s.start_time > new Date()}
<span class="bg-orange-200 rounded-lg px-2 py-1">Programmée</span>
{:else}
<span class="bg-red-200 rounded-lg px-2 py-1">Terminée</span>
{/if}
</td>
<td class="py-2">{s.otherUsersList(5)}</td>
<td class="py-2">4 messages</td>
<td class="py-2">
<a href="/session?id={s.id}">
<Icon
src={ArrowRightCircle}
size="32"
class="text-accent float-end hover:text-white hover:bg-accent hover:cursor-pointer rounded-full"
/>
</a>
</td>
<th scope="col" class="text-left">{$t('utils.words.date')}</th>
<th scope="col">{$t('utils.words.status')}</th>
<th scope="col"># {$t('utils.words.messages').toLowerCase()}</th>
<th scope="col">{$t('utils.words.actions')}</th>
</tr>
{/each}
</tbody>
</table>
</thead>
<tbody class="divide-y divide-neutral-200">
{#if contactSessions.length === 0}
<tr>
<td colspan="4" class="py-5 text-gray-500">{$t('home.noSessions')}</td>
</tr>
{:else}
{#if !showTerminatedSessions && contactSessions.filter((s) => s.end_time >= new Date()).length === 0}
<tr>
<td colspan="4" class="py-5 text-gray-500"
>{$t('home.noCurrentOrFutureSessions')}</td
>
</tr>
{/if}
{#each contactSessions as s (s.id)}
{#if showTerminatedSessions || s.end_time >= new Date()}
<tr>
<td class="py-2 text-left space-y-1">
<div>
{displayShortTime(s.start_time)}
</div>
<div class="text-sm italic text-gray-600">
{displayTimeSince(s.start_time)}
</div>
</td>
<td class="py-2">
{#if s.start_time <= new Date() && s.end_time >= new Date()}
<span class="bg-green-200 rounded-lg px-2 py-1"
>{$t('utils.words.inProgress')}</span
>
{:else if s.start_time > new Date()}
<span class="bg-orange-200 rounded-lg px-2 py-1"
>{$t('utils.words.programed')}</span
>
{:else}
<span class="bg-red-200 rounded-lg px-2 py-1"
>{$t('utils.words.finished')}</span
>
{/if}
</td>
<td class="py-2">{s.length} {$t('utils.words.messages').toLowerCase()}</td>
<td class="py-2">
<a href="/session?id={s.id}" class="group">
<Icon
src={ArrowRightCircle}
size="32"
class="text-accent mx-auto group-hover:text-white group-hover:bg-accent rounded-full"
/>
</a>
</td>
</tr>
{/if}
{/each}
<tr>
<td
class="py-2 hover:cursor-pointer"
colspan="4"
on:click={() => (showTerminatedSessions = !showTerminatedSessions)}
>
<button aria-label={showTerminatedSessions ? 'Hide' : 'Show'}>
<svg
class="size-3 ms-3"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 10 6"
class:rotate-180={showTerminatedSessions}
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m1 1 4 4 4-4"
/>
</svg>
</button>
</td>
</tr>
{/if}
</tbody>
</table>
</div>
</div>
{/if}
</div>
{/if}
<dialog
class="modal"
class="modal bg-black bg-opacity-50"
open={modalNew}
on:close={() => (modalNew = false)}
on:keydown={(e) => e.key === 'Escape' && (modalNew = false)}
tabindex="0"
tabindex="-1"
>
<div class="modal-box">
<h2 class="text-xl font-bold mb-4">{$t('home.newContact')}</h2>
......@@ -228,6 +303,7 @@
placeholder={$t('home.email')}
bind:value={nickname}
class="input flex-grow mr-2"
on:keydown={(e) => e.key === 'Escape' && (modalNew = false)}
/>
<button class="button w-16" on:click={searchNickname}>
<Icon src={MagnifyingGlass} />
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter