diff --git a/src/App.js b/src/App.js
index 79d22e61d175190fabf0f5e644228560da115184..eb90662679b003941ada3ceeefe7bde28f0e3e64 100644
--- a/src/App.js
+++ b/src/App.js
@@ -17,6 +17,7 @@ import automated_transactions from "./resources/AutomatedTransactions";
 import events from './resources/Events';
 import members from './resources/Members';
 import movements from "./resources/Movements";
+import participations from './resources/Participations';
 import people from './resources/People';
 import personal_accounts from "./resources/PersonalAccounts";
 import personal_transactions from "./resources/PersonalTransactions";
@@ -58,6 +59,7 @@ export default class App extends Component {
                 <Resource name="personal_accounts" {...personal_accounts} />
                 <Resource name="personal_transactions" {...personal_transactions} />
                 <Resource name="events" {...events} />
+                <Resource name="participations" {...participations} />
             </Admin>
         );
     }
diff --git a/src/components/PaymentInput.js b/src/components/PaymentInput.js
index 0c0917d39b2230343ea0eba8968f25271d556d0d..51aad16c1343ced2dc1e98a3879db02c5de43463 100644
--- a/src/components/PaymentInput.js
+++ b/src/components/PaymentInput.js
@@ -3,15 +3,15 @@ import React from "react";
 import { FormDataConsumer, SelectInput, useTranslate } from 'react-admin';
 import PersonalAccountSelector from "../components/PersonalAccountSelector";
 
-const PaymentInput = ({ price }) => {
+const PaymentInput = ({ price, optional = false }) => {
     const translate = useTranslate();
     return (<>
         <MuiTextField value={Number(price).toLocaleString('fr-FR', { currency: 'EUR', currencyDisplay: 'symbol', style: 'currency' })} disabled variant="filled" type="text" label={translate('inputs.multiproductcount.price')} />
-        <SelectInput source="payment" label="Moyen de paiement" allowEmpty={false} choices={[
+        <SelectInput source="payment" label="Moyen de paiement" allowEmpty={optional} choices={[
             { id: 'cash', name: 'Liquide (Caisse)' },
             { id: 'card', name: 'Carte Bancaire' },
             { id: 'account', name: 'Compte personel' },
-        ]} initialValue='cash' />
+        ]} initialValue={optional ? null : 'cash'} />
         <FormDataConsumer>
             {({ formData, ...rest }) => formData.payment === 'account' &&
                 <PersonalAccountSelector source="token" label="Compte" />
diff --git a/src/layout/Menu.js b/src/layout/Menu.js
index 1c059a54800c06f09e8be2670ddb52bdd8bb9427..ac0c7da5f46b7a7044c6ac4df244beb999a0ec50 100644
--- a/src/layout/Menu.js
+++ b/src/layout/Menu.js
@@ -21,6 +21,7 @@ import ImportExportIcon from '@material-ui/icons/ImportExport';
 import LocalCafeIcon from '@material-ui/icons/LocalCafe';
 import LocalOfferIcon from '@material-ui/icons/LocalOffer';
 import MoneyIcon from '@material-ui/icons/Money';
+import PersonAddIcon from '@material-ui/icons/PersonAdd';
 import ShoppingCartIcon from '@material-ui/icons/ShoppingCart';
 import SwapHorizIcon from '@material-ui/icons/SwapHoriz';
 import * as React from 'react';
@@ -105,6 +106,7 @@ const Menu = ({ onMenuClick, logout }) => {
             <Item to="/purchases/create" permissions="purchases.create" primaryText={translate('menu.left.buy')} leftIcon={<ShoppingCartIcon />} />
             <Item to="/accounts_counts/create" permissions="accounts_counts.create" primaryText={translate('menu.left.count_money')} leftIcon={<MoneyIcon />} />
             <Item to="/products_counts/create" permissions="products_counts.create" primaryText={translate('menu.left.count_stocks')} leftIcon={<BarChartIcon />} />
+            <Item to="/participations/create" permissions="participations.create" primaryText={translate('menu.left.add_participant')} leftIcon={<EventIcon />} />
             <Accordeon open={false} title={translate('menu.left.humans')} permissions={["people.show", "members.show", "users.show"]}>
                 <Item to="/people" permissions="people.show" primaryText={translate('menu.left.people')} leftIcon={<EmojiPeopleIcon />} />
                 <Item to="/members" permissions="members.show" primaryText={translate('menu.left.members')} leftIcon={<GroupIcon />} />
@@ -128,8 +130,9 @@ const Menu = ({ onMenuClick, logout }) => {
                 <Item to="/purchases" permissions="purchases.show" primaryText={translate('menu.left.purchases')} leftIcon={<ShoppingCartIcon />} />
                 <Item to="/transferts" permissions="transferts.show" primaryText={translate('menu.left.transferts')} leftIcon={<ImportExportIcon />} />
             </Accordeon>
-            <Accordeon open={false} title={translate('menu.left.events')} permissions={["events.show"]}>
+            <Accordeon open={false} title={translate('menu.left.events')} permissions={["events.show", "participations.show"]}>
                 <Item to="/events" permissions="events.show" primaryText={translate('menu.left.events')} leftIcon={<EventIcon />} />
+                <Item to="/participations" permissions="participations.show" primaryText={translate('menu.left.participations')} leftIcon={<PersonAddIcon />} />
             </Accordeon>
             <Accordeon open={false} title={translate('menu.left.archives')} permissions={["archived_members.show"]}>
                 <Item to="/archived_members" permissions="archived_members.show" primaryText={translate('menu.left.archived_members')} leftIcon={<GroupIcon />} />
@@ -139,5 +142,4 @@ const Menu = ({ onMenuClick, logout }) => {
         </>
     );
 };
-
 export { Menu };
diff --git a/src/providers/I18nProvider.js b/src/providers/I18nProvider.js
index aed52bf903e7b10dca09863e556cdff16132a004..f7bbeb9c3265276319b3505a0a54b230e99e51b1 100644
--- a/src/providers/I18nProvider.js
+++ b/src/providers/I18nProvider.js
@@ -84,6 +84,7 @@ const messages = {
                 buy: "Acheter",
                 count_money: "Compter les comptes",
                 count_stocks: "Compter les stocks",
+                add_participant: "Ajouter un participant",
                 members: "Membres",
                 stocks: "Stocks",
                 products: "Produits",
@@ -113,7 +114,8 @@ const messages = {
                 personal_transactions: "Transactions Personnelles",
                 personal_refills: "Recharge Compte Perso.",
                 refill: "Recharger",
-                events: "Évènements"
+                events: "Évènements",
+                participations: "Participants"
             }
         },
         resources: {
@@ -391,6 +393,17 @@ const messages = {
                     password_changed_at: 'MDP changé le'
                 }
             },
+            participations: {
+                name: 'Participation |||| Participations',
+                fields: {
+                    id: "#",
+                    created_at: 'Créé le',
+                    updated_at: 'Modifié le',
+                    event_id: "Évènement",
+                    person_id: "Personne",
+                    transaction_id: "Transaction"
+                }
+            },
             profile: {
                 name: 'Profile',
                 fields: {
diff --git a/src/resources/Participations.js b/src/resources/Participations.js
new file mode 100644
index 0000000000000000000000000000000000000000..12882b4c808e9cc0c43fb31a157eeff97e844efb
--- /dev/null
+++ b/src/resources/Participations.js
@@ -0,0 +1,301 @@
+import { capitalize, FormControl, FormControlLabel, InputLabel, MenuItem, Select, Switch, TextField as MuiTextField, useMediaQuery } from '@material-ui/core';
+import CheckIcon from '@material-ui/icons/Check';
+import CloseIcon from '@material-ui/icons/Close';
+import React, { useEffect, useState } from "react";
+import { AutocompleteInput, BooleanField, Create, Datagrid, DateField, Edit, EditButton, Error, FormDataConsumer, FormTab, FunctionField, Labeled, List, Loading, ReferenceField, ReferenceInput, ShowButton, SimpleList, SimpleShowLayout, TabbedForm, TextField, useInput, useNotify, useQuery, useRefresh, useTranslate } from 'react-admin';
+import { ShowDialog } from '../components/DialogForm';
+import PaymentInput from "../components/PaymentInput";
+
+const ParticipationFilters = [
+    <ReferenceInput source="event_id" reference="events" filterToQuery={searchText => ({ name: searchText })}>
+        <AutocompleteInput optionText="name" />
+    </ReferenceInput>,
+    <ReferenceInput source="person_id" reference="people" filterToQuery={searchText => ({ fullname: searchText, has_account: true })}>
+        <AutocompleteInput optionText="fullname" />
+    </ReferenceInput>
+];
+
+const EventDataField = (props) => {
+    const { data, loading, error } = useQuery({
+        type: 'getOne',
+        resource: 'events',
+        payload: { id: props.record.event_id }
+    });
+
+    if (loading) return <Loading />;
+    if (error) return <Error />;
+    if (!data) return null;
+
+    return data.data.map((val, i) => {
+        if (val.type === "bool") {
+            return (<Labeled key={i} label={capitalize(val.name)}>
+                <BooleanField source={"data." + val.name} record={props.record} />
+            </Labeled>);
+        } else {
+            return (<Labeled key={i} label={capitalize(val.name)}>
+                <TextField source={"data." + val.name} label={val.name} record={props.record} />
+            </Labeled>);
+        }
+    });
+};
+
+const MultiButton = (props) => {
+    if (props?.record?.transaction_id === null || props?.record?.transaction_id === undefined) {
+        return <EditButton {...props} />;
+    } else {
+        return <ShowButton {...props} />;
+    }
+}
+
+const Participation = (props) => {
+    const isDesktop = useMediaQuery(theme => theme.breakpoints.up('md'));
+    return (
+        <>
+            <List {...props} filters={ParticipationFilters} bulkActionButtons={false}>
+                {isDesktop ? (
+                    <Datagrid>
+                        <TextField source="id" />
+                        <ReferenceField source="event_id" reference="events" link="show">
+                            <TextField source="name" />
+                        </ReferenceField>
+                        <ReferenceField source="person_id" reference="people" link="show" >
+                            <FunctionField render={r => r.firstname + " " + r.lastname} />
+                        </ReferenceField>
+                        <ReferenceField source="transaction_id" reference="transactions" link="show">
+                            <TextField source="name" />
+                        </ReferenceField>
+                        <MultiButton />
+                    </Datagrid>
+                ) : (
+                    <SimpleList
+                        secondaryText={record =>
+                            <ReferenceField record={record} source="event_id" reference="events" link={false}>
+                                <TextField source="name" />
+                            </ReferenceField>}
+                        primaryText={record =>
+                            <ReferenceField record={record} source="person_id" reference="people" link={false} >
+                                <FunctionField render={r => r.firstname + " " + r.lastname} />
+                            </ReferenceField>}
+                        tertiaryText={record => (record.transaction_id === null ? <CloseIcon /> : <CheckIcon />)}
+                        linkType="show"
+                    />
+                )}
+            </List>
+            <ShowDialog>
+                <SimpleShowLayout>
+                    <TextField source="id" />
+                    <ReferenceField source="event_id" reference="events" link="show">
+                        <TextField source="name" />
+                    </ReferenceField>
+                    <ReferenceField source="person_id" reference="people" link="show" >
+                        <FunctionField render={r => r.firstname + " " + r.lastname} />
+                    </ReferenceField>
+                    <ReferenceField source="transaction_id" reference="transactions" link="show">
+                        <TextField source="name" />
+                    </ReferenceField>
+                    <EventDataField />
+                    <DateField source="created_at" />
+                    <DateField source="updated_at" />
+                </SimpleShowLayout>
+            </ShowDialog>
+        </>
+    );
+};
+
+const eventPrice = (event, person, data) => {
+    const member = person.is_member;
+    let price = member ? event.price_member : event.price;
+
+    for (let dat of event.data) {
+        if (dat.type === "boolean") {
+            if (data[dat.name] === true) {
+                price += member ? dat.price_member : dat.price;
+            }
+        } else if (dat.type === "select") {
+            for (let val of dat.values) {
+                if (data[dat.name] === val.name) {
+                    price += member ? val.price_member : val.price;
+                    break;
+                }
+            }
+        }
+    }
+
+    return price;
+}
+
+const EventDataInput = ({ eventId, personId, priceChanged, ...props }) => {
+    // TODO: Calculate and report price
+    const {
+        input: { name, onChange, initialValue },
+        meta: { touched, error },
+        isRequired
+    } = useInput(props);
+    console.log(initialValue);
+
+    const [value, setValue] = useState({});
+
+    const { data: event, loading: loading1, error: error1 } = useQuery({
+        type: 'getOne',
+        resource: 'events',
+        payload: { id: eventId }
+    });
+
+    const { data: person, loading: loading2, error: error2 } = useQuery({
+        type: 'getOne',
+        resource: 'people',
+        payload: { id: personId }
+    });
+
+    const onChangeWrapper = (name) => {
+        return (e) => {
+            let val = { ...value };
+            val[name] = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
+            setValue(val);
+            onChange(val);
+        }
+    }
+
+    useEffect(() => {
+        if (priceChanged !== undefined && event !== undefined && person !== undefined && value !== undefined)
+            priceChanged(eventPrice(event, person, value));
+    }, [event, person, value]);
+
+    useEffect(() => {
+        let val = {};
+
+        event?.data?.map((v) => {
+            if (v.type === "boolean") {
+                val[v.name] = false;
+            } else if (v.type === "select") {
+                val[v.name] = v.values[0]?.name;
+            } else {
+                val[v.name] = "";
+            }
+        });
+
+        setValue(val);
+    }, [event]);
+
+    if (loading1 || loading2) return <Loading />;
+    if (error1 || error2) return <Error />;
+    if ((!event) || (!person)) return null;
+
+    return event.data.map((structure, index) => {
+        if (structure.type === "boolean") {
+
+            return <FormControlLabel key={index} margin="normal"
+                control={<Switch checked={value[structure.name] ?? false} onChange={onChangeWrapper(structure.name)} name={structure.name} />}
+                label={capitalize(structure.name)}
+            />;
+        } else if (structure.type === "select") {
+            return <FormControl key={index} variant="filled" margin="normal">
+                <InputLabel id={"data-" + index}>{capitalize(structure.name)}</InputLabel>
+                <Select
+                    labelId={"data-" + index}
+                    id={"data-select-" + index}
+                    value={value[structure.name] ?? ""}
+                    onChange={onChangeWrapper(structure.name)}
+                >
+                    {structure.values.map((item, i) => {
+                        return <MenuItem value={item.name} key={i}>{capitalize(item.name)}</MenuItem>
+                    })}
+                </Select>
+            </FormControl>;
+        } else {
+            return <MuiTextField key={index} name={structure.name} label={capitalize(structure.name)} onChange={onChangeWrapper(structure.name)} value={value[structure.name] ?? ""} variant="filled" margin="normal" size="small" />;
+        }
+    });
+};
+
+const EditParticipation = props => {
+    const translate = useTranslate();
+    const refresh = useRefresh();
+    const notify = useNotify();
+
+    const [price, setPrice] = useState(0);
+
+    return <>
+        <Edit {...props} onSuccess={() => {
+            notify('ra.notification.created', 'info', { smart_count: 1 });
+            refresh();
+        }}>
+            <TabbedForm syncWithLocation={false}>
+                <FormTab label="Produits">
+                    <ReferenceField source="event_id" reference="events" link="show">
+                        <TextField source="name" />
+                    </ReferenceField>
+                    <ReferenceField source="person_id" reference="people" link="show" >
+                        <FunctionField render={r => r.firstname + " " + r.lastname} />
+                    </ReferenceField>
+                    <ReferenceField source="transaction_id" reference="transactions" link="show">
+                        <TextField source="name" />
+                    </ReferenceField>
+                    <FormDataConsumer>
+                        {({ formData, ...rest }) => {
+                            if (formData.event_id === undefined || formData.person_id === undefined || (formData.transaction_id !== null && formData.transaction_id !== undefined))
+                                return null;
+                            return <EventDataInput priceChanged={setPrice} source="data" key={formData.event_id + " " + formData.person_id} eventId={formData.event_id} personId={formData.person_id} />;
+                        }}
+                    </FormDataConsumer>
+                    <MuiTextField value={Number(price).toLocaleString('fr-FR', { currency: 'EUR', currencyDisplay: 'symbol', style: 'currency' })} disabled variant="filled" type="text" label={translate('inputs.multiproductcount.price')} />
+                </FormTab>
+                <FormTab label="Paiement">
+                    <FormDataConsumer>
+                        {({ formData, ...rest }) => {
+                            if (formData.transaction_id !== null && formData.transaction_id !== undefined)
+                                return null;
+                            return <PaymentInput price={price} optional />;
+                        }}
+                    </FormDataConsumer>
+                </FormTab>
+            </TabbedForm>
+        </Edit>
+    </>
+};
+
+const AddParticipation = props => {
+    const refresh = useRefresh();
+    const notify = useNotify();
+    const translate = useTranslate();
+
+    const [price, setPrice] = useState(0);
+
+    return <>
+        <Create {...props} onSuccess={() => {
+            notify('ra.notification.created', 'info', { smart_count: 1 });
+            refresh();
+        }}>
+            <TabbedForm syncWithLocation={false}>
+                <FormTab label="Produits">
+                    <ReferenceInput source="event_id" reference="events" filterToQuery={searchText => ({ name: searchText })}>
+                        <AutocompleteInput optionText="name" />
+                    </ReferenceInput>
+                    <ReferenceInput source="person_id" reference="people" filterToQuery={searchText => ({ fullname: searchText })}>
+                        <AutocompleteInput optionText="fullname" />
+                    </ReferenceInput>
+                    <FormDataConsumer>
+                        {({ formData, ...rest }) => {
+                            if (formData.event_id === undefined || formData.person_id === undefined)
+                                return null;
+                            return <EventDataInput priceChanged={setPrice} source="data" key={formData.event_id + " " + formData.person_id} eventId={formData.event_id} personId={formData.person_id} />;
+                        }}
+                    </FormDataConsumer>
+                    <MuiTextField value={Number(price).toLocaleString('fr-FR', { currency: 'EUR', currencyDisplay: 'symbol', style: 'currency' })} disabled variant="filled" type="text" label={translate('inputs.multiproductcount.price')} />
+                </FormTab>
+                <FormTab label="Paiement">
+                    <PaymentInput price={price} optional />
+                </FormTab>
+            </TabbedForm>
+        </Create>
+    </>
+};
+
+const participations = {
+    list: Participation,
+    create: AddParticipation,
+    edit: EditParticipation,
+    show: Participation
+};
+
+export default participations;