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
Ce commit fait partie de la requête de fusion !6. Les commentaires créés ici seront créés dans le contexte de cette requête de fusion.
...@@ -77,12 +77,20 @@ def create_user_survey_weekly(db: Session, user_id: int, survey: schemas.SurveyC ...@@ -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): def get_contact_sessions(db: Session, user_id: int, contact_id: int):
return ( sessions = (
db.query(models.Session) db.query(models.Session)
.filter(models.Session.users.any(models.User.id == user_id)) .filter(models.Session.users.any(models.User.id == user_id))
.filter(models.Session.users.any(models.User.id == contact_id)) .filter(models.Session.users.any(models.User.id == contact_id))
.all() .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): def create_session(db: Session, user: schemas.User):
......
...@@ -22,10 +22,7 @@ ...@@ -22,10 +22,7 @@
"history": "Historique" "history": "Historique"
}, },
"home": { "home": {
"date": "Date",
"participants": "Participants",
"email": "E-mail", "email": "E-mail",
"actions": "Actions",
"add": "Ajouter", "add": "Ajouter",
"deleteSessionConfirm": "Êtes-vous sûr de vouloir supprimer cette session ? Cette action est irréversible.", "deleteSessionConfirm": "Êtes-vous sûr de vouloir supprimer cette session ? Cette action est irréversible.",
"createSession": "Session immédiate", "createSession": "Session immédiate",
...@@ -42,7 +39,9 @@ ...@@ -42,7 +39,9 @@
"pastSessions": "Sessions terminées", "pastSessions": "Sessions terminées",
"newContact": "Ajouter un contact", "newContact": "Ajouter un contact",
"bookingSuccessful": "Session réservée avec succès", "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": { "login": {
"email": "E-mail", "email": "E-mail",
...@@ -286,6 +285,20 @@ ...@@ -286,6 +285,20 @@
"november": "novembre", "november": "novembre",
"december": "décembre" "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": { "days": {
"monday": "Lundi", "monday": "Lundi",
"tuesday": "Mardi", "tuesday": "Mardi",
...@@ -324,7 +337,13 @@ ...@@ -324,7 +337,13 @@
"words": { "words": {
"date": "Date", "date": "Date",
"messages": "Messages", "messages": "Messages",
"actions": "Actions" "actions": "Actions",
"participants": "Participants",
"status": "Statut",
"date": "Date",
"programed": "Programmée",
"inProgress": "En cours",
"finished": "Terminée"
} }
}, },
"inputs": { "inputs": {
......
...@@ -32,6 +32,37 @@ export function getFullMonth(id: number): string { ...@@ -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 { export function displayDate(date: Date): string {
if (date === null) return ''; if (date === null) return '';
...@@ -110,16 +141,16 @@ export function formatToUTCDate(date: Date): string { ...@@ -110,16 +141,16 @@ export function formatToUTCDate(date: Date): string {
} }
export function displayShortTime(date: Date): string { export function displayShortTime(date: Date): string {
const now = new Date();
return ( return (
('0' + date.getDate()).slice(-2) + ('0' + date.getDate()).slice(-2) +
'/' + ' ' +
('0' + (date.getMonth() + 1)).slice(-2) + getShortMonth(date.getMonth()) +
'/' + (date.getFullYear() != now.getFullYear() ? ' ' + date.getFullYear() : '') +
date.getFullYear() +
' ' + ' ' +
('0' + date.getHours()).slice(-2) + ('0' + date.getHours()).slice(-2) +
':' + 'h'
('0' + date.getMinutes()).slice(-2)
); );
} }
......
<script lang="ts"> <script lang="ts">
import Session from '$lib/types/session'; import Session from '$lib/types/session';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { displayShortTime, displayTime, displayTimeSince } from '$lib/utils/date'; import { displayShortTime, displayTimeSince } from '$lib/utils/date';
import { import {
AcademicCap, AcademicCap,
Sparkles, Sparkles,
Icon, Icon,
User as UserIcon, User as UserIcon,
MagnifyingGlass, MagnifyingGlass,
ArrowRight,
ArrowRightCircle ArrowRightCircle
} from 'svelte-hero-icons'; } from 'svelte-hero-icons';
import { t } from '$lib/services/i18n'; import { t } from '$lib/services/i18n';
...@@ -29,7 +28,10 @@ ...@@ -29,7 +28,10 @@
let modalNew = false; let modalNew = false;
let nickname = ''; let nickname = '';
let showTerminatedSessions = false;
async function selectContact(c: User | null) { async function selectContact(c: User | null) {
showTerminatedSessions = false;
contact = c; contact = c;
if (!contact) { if (!contact) {
contactSessions = []; contactSessions = [];
...@@ -138,87 +140,160 @@ ...@@ -138,87 +140,160 @@
} }
</script> </script>
<svelte:head>
<script>
</script>
</svelte:head>
{#if ready} {#if ready}
<div class="flex-col flex p-4 lg:w-[64rem] lg:mx-auto"> <div class="flex-row h-full flex py-4 flex-grow overflow-y-hidden">
{#if contact} <div class="flex flex-col border shadow-[0_0_6px_0_rgba(0,14,156,.2)] min-w-72 rounded-r-xl">
<div> <div class="flex-grow">
<button on:click|preventDefault={createSession} class="button float-start mr-2"> {#each contacts as c (c.id)}
{$t('home.createSession')} <div
</button> class="h-24 flex border-gray-300 border-b-2 hover:bg-gray-200 hover:cursor-pointer p-4"
<button class:bg-gray-200={c.id === contact?.id}
class="button float-start" on:click={() => selectContact(c)}
class:btn-disabled={!contact || !contact.calcom_link} role="button"
data-cal-link={`${contact.calcom_link}?email=${$user?.email}&name=${$user?.nickname}`} aria-label={c.nickname}
> tabindex="0"
{$t('home.bookSession')} on:keydown={(e) => e.key === 'Enter' && selectContact(c)}
</button> >
<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>
<div <button
class="border p-4 mt-4 rounded-xl shadow-[0_0_6px_0_rgba(0,14,156,.2)] overflow-y-scroll no-scrollbar" 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> </button>
<tr> </div>
<th scope="col" class="text-left">Date</th> {#if contact}
<th scope="col">Status</th> <div class="flex flex-col xl:mx-auto xl:w-[60rem] m-4">
<th scope="col">Participants</th> <div>
<th scope="col"># messages</th> <button on:click|preventDefault={createSession} class="button float-start mr-2">
<th scope="col"></th> {$t('home.createSession')}
</tr> </button>
</thead> <button
<tbody class="divide-y divide-neutral-200"> class="button float-start"
{#each contactSessions as s (s.id)} 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> <tr>
<td class="py-2 text-left"> <th scope="col" class="text-left">{$t('utils.words.date')}</th>
<div> <th scope="col">{$t('utils.words.status')}</th>
{displayShortTime(s.start_time)} <th scope="col"># {$t('utils.words.messages').toLowerCase()}</th>
</div> <th scope="col">{$t('utils.words.actions')}</th>
<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>
</tr> </tr>
{/each} </thead>
</tbody> <tbody class="divide-y divide-neutral-200">
</table> {#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> </div>
{/if} {/if}
</div> </div>
{/if} {/if}
<dialog <dialog
class="modal" class="modal bg-black bg-opacity-50"
open={modalNew} open={modalNew}
on:close={() => (modalNew = false)} on:close={() => (modalNew = false)}
on:keydown={(e) => e.key === 'Escape' && (modalNew = false)} tabindex="-1"
tabindex="0"
> >
<div class="modal-box"> <div class="modal-box">
<h2 class="text-xl font-bold mb-4">{$t('home.newContact')}</h2> <h2 class="text-xl font-bold mb-4">{$t('home.newContact')}</h2>
...@@ -228,6 +303,7 @@ ...@@ -228,6 +303,7 @@
placeholder={$t('home.email')} placeholder={$t('home.email')}
bind:value={nickname} bind:value={nickname}
class="input flex-grow mr-2" class="input flex-grow mr-2"
on:keydown={(e) => e.key === 'Escape' && (modalNew = false)}
/> />
<button class="button w-16" on:click={searchNickname}> <button class="button w-16" on:click={searchNickname}>
<Icon src={MagnifyingGlass} /> <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