Write a POC of estimation session

This commit is contained in:
Pijus Kamandulis
2024-10-06 15:15:36 +03:00
parent 6fc1b81fd9
commit 45039d356f
15 changed files with 714 additions and 57 deletions

View File

@@ -0,0 +1,48 @@
import { useForm } from '@tanstack/react-form';
import { useEstimationSessions } from '../lib/context/estimationSession';
import { useUser } from '../lib/context/user';
const CreateEstimationSession = () => {
const user = useUser();
const estimationSessions = useEstimationSessions();
const form = useForm({
defaultValues: {
name: '',
},
onSubmit: async ({ value }) => {
await estimationSessions?.add({
Name: value.name,
UserId: user.current?.$id,
});
},
});
return (
<>
<h1>Create Estimation Session</h1>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
form.handleSubmit();
}}
>
<form.Field
name="name"
children={(field) => (
<input
placeholder="Name"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
/>
<button type="submit">Submit</button>
</form>
</>
);
};
export default CreateEstimationSession;

View File

@@ -0,0 +1,110 @@
import { getRouteApi } from '@tanstack/react-router';
import { useEstimationSessions } from '../lib/context/estimationSession';
import { useForm } from '@tanstack/react-form';
import { useUser } from '../lib/context/user';
const route = getRouteApi('/estimate/session/$sessionId');
const EstimationSession = () => {
const { sessionId } = route.useParams();
const user = useUser();
const estimationSessions = useEstimationSessions();
const estimationSession = estimationSessions?.current.find(
(x) => x.$id == sessionId,
);
const tickets = estimationSessions?.getTickets(sessionId);
const currentState = estimationSessions?.getState(sessionId);
const createTicketForm = useForm({
defaultValues: {
name: '',
},
onSubmit: async ({ value }) => {
await estimationSessions?.addTicket(sessionId, {
Name: value.name,
});
},
});
return (
<>
<h1>Estimation Session - {estimationSession?.Name}</h1>
<div>
<h2>Tasks</h2>
{tickets?.map((x) => (
<div key={x.Id}>
{x.Id} - {x.Name}
<button
onClick={() => estimationSessions?.selectTicket(sessionId, x.Id)}
>
Select
</button>
</div>
))}
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
createTicketForm.handleSubmit();
}}
>
<createTicketForm.Field
name="name"
children={(field) => (
<input
placeholder="Name"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
/>
<button type="submit">Submit</button>
</form>
</div>
{currentState?.CurrentTicketId && (
<div>
<h2>
{currentState.CurrentTicketId} -{' '}
{tickets?.find((x) => x.Id === currentState.CurrentTicketId)?.Name}
</h2>
{[0.5, 1, 2, 3, 5, 8, 13, 21].map((estimate) => (
<button
key={estimate}
onClick={() =>
estimationSessions?.voteEstimate(
sessionId,
currentState.CurrentTicketId,
estimate,
user.current?.$id ?? '',
)
}
>
{estimate}
</button>
))}
{currentState.VotesRevealed ? (
<>
<h3>Votes</h3>
<ul>
{currentState.Votes.map((vote) => (
<li key={vote.UserId}>
{vote.UserId} - {vote.Estimate}
</li>
))}
</ul>
</>
) : (
<button onClick={() => estimationSessions?.revealVotes(sessionId)}>
Reveal Votes
</button>
)}
</div>
)}
<pre>Session Id: {sessionId}</pre>
</>
);
};
export default EstimationSession;

34
src/pages/Home.css Normal file
View File

@@ -0,0 +1,34 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

46
src/pages/Home.tsx Normal file
View File

@@ -0,0 +1,46 @@
import reactLogo from '../assets/react.svg';
import viteLogo from '/vite.svg';
import './Home.css';
import { Link } from '@tanstack/react-router';
import { useUser } from '../lib/context/user';
import { useEstimationSessions } from '../lib/context/estimationSession';
function Home() {
const user = useUser();
const estimationSessions = useEstimationSessions();
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Scrummie-Poker</h1>
<ul>
<li>
<Link to="/login">Login</Link>
</li>
<li>
<Link to="/estimate/new">Create Estimation Session</Link>
</li>
</ul>
<pre>User Id: {user.current?.$id}</pre>
<div>
<p>Estimation sessions</p>
{estimationSessions?.current.map((session) => (
<Link key={session.$id} to={`/estimate/session/${session.$id}`}>
{session.Name}
</Link>
))}
</div>
</>
);
}
export default Home;

72
src/pages/Login.tsx Normal file
View File

@@ -0,0 +1,72 @@
import { useForm } from '@tanstack/react-form';
import { useUser } from '../lib/context/user';
const Login = () => {
const user = useUser();
const form = useForm({
defaultValues: {
email: '',
password: '',
},
onSubmit: async ({ value }) => {
console.log({ value });
},
});
return (
<>
<h1>Login or register</h1>
<form>
<form.Field
name="email"
children={(field) => (
<input
type="email"
placeholder="Email"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
/>
<form.Field
name="password"
children={(field) => (
<input
type="password"
placeholder="Password"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
/>
<div>
<button
className="button"
type="button"
onClick={() =>
user.login(form.state.values.email, form.state.values.password)
}
>
Login
</button>
<button
className="button"
type="button"
onClick={() =>
user.register(form.state.values.email, form.state.values.password)
}
>
Register
</button>
</div>
</form>
<button onClick={() => user.loginAsGuest()}>Login as guest</button>
</>
);
};
export default Login;