diff --git a/app/components/create-settings.hbs b/app/components/create-settings.hbs
new file mode 100644
index 0000000..e458468
--- /dev/null
+++ b/app/components/create-settings.hbs
@@ -0,0 +1,113 @@
+
\ No newline at end of file
diff --git a/app/components/create-settings.ts b/app/components/create-settings.ts
new file mode 100644
index 0000000..dd1aa31
--- /dev/null
+++ b/app/components/create-settings.ts
@@ -0,0 +1,188 @@
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { action } from '@ember/object';
+import { service } from '@ember/service';
+import { isPresent } from '@ember/utils';
+import { DateTime, Duration } from 'luxon';
+import { generatePassphrase } from '../utils/encryption';
+import Poll from '../models/poll';
+import type IntlService from 'ember-intl/services/intl';
+import type RouterService from '@ember/routing/router-service';
+import type { CreateSettingsRouteModel } from 'croodle/routes/create/settings';
+
+export interface CreateSettingsSignature {
+ Args: {
+ poll: CreateSettingsRouteModel;
+ };
+}
+
+export default class CreateSettingsComponent extends Component {
+ @service declare intl: IntlService;
+ @service declare router: RouterService;
+
+ @tracked savingPollFailed = false;
+
+ get anonymousUser() {
+ return this.args.poll.anonymousUser;
+ }
+ set anonymousUser(value) {
+ this.args.poll.anonymousUser = value;
+ }
+
+ get answerType() {
+ return this.args.poll.answerType;
+ }
+ set answerType(value) {
+ this.args.poll.answerType = value;
+ }
+
+ get answerTypes() {
+ return [
+ { id: 'YesNo', labelTranslation: 'answerTypes.yesNo.label' },
+ { id: 'YesNoMaybe', labelTranslation: 'answerTypes.yesNoMaybe.label' },
+ { id: 'FreeText', labelTranslation: 'answerTypes.freeText.label' },
+ ];
+ }
+
+ get expirationDuration() {
+ // TODO: must be calculated based on model.expirationDate
+ return 'P3M';
+ }
+ set expirationDuration(value) {
+ this.args.poll.expirationDate = isPresent(value)
+ ? (DateTime.local().plus(Duration.fromISO(value)).toISO() as string)
+ : '';
+ }
+
+ get expirationDurations() {
+ return [
+ {
+ id: 'P7D',
+ labelTranslation: 'create.settings.expirationDurations.P7D',
+ },
+ {
+ id: 'P1M',
+ labelTranslation: 'create.settings.expirationDurations.P1M',
+ },
+ {
+ id: 'P3M',
+ labelTranslation: 'create.settings.expirationDurations.P3M',
+ },
+ {
+ id: 'P6M',
+ labelTranslation: 'create.settings.expirationDurations.P6M',
+ },
+ {
+ id: 'P1Y',
+ labelTranslation: 'create.settings.expirationDurations.P1Y',
+ },
+ { id: '', labelTranslation: 'create.settings.expirationDurations.never' },
+ ];
+ }
+
+ get forceAnswer() {
+ return this.args.poll.forceAnswer;
+ }
+ set forceAnswer(value) {
+ this.args.poll.forceAnswer = value;
+ }
+
+ @action
+ previousPage() {
+ const { pollType } = this.args.poll;
+
+ if (pollType === 'FindADate') {
+ this.router.transitionTo('create.options-datetime');
+ } else {
+ this.router.transitionTo('create.options');
+ }
+ }
+
+ @action
+ async createPoll() {
+ const { poll } = this.args;
+ const {
+ anonymousUser,
+ answerType,
+ description,
+ expirationDate,
+ forceAnswer,
+ freetextOptions,
+ dateOptions,
+ timesForDateOptions,
+ pollType,
+ title,
+ } = poll;
+
+ // calculate options
+ const options: string[] = [];
+ if (pollType === 'FindADate') {
+ // merge date with times
+ for (const date of dateOptions) {
+ if (timesForDateOptions.has(date)) {
+ for (const time of timesForDateOptions.get(date)!) {
+ const [hour, minute] = time.split(':') as [string, string];
+ options.push(
+ DateTime.fromISO(date)
+ .set({
+ hour: parseInt(hour),
+ minute: parseInt(minute),
+ second: 0,
+ millisecond: 0,
+ })
+ .toISO() as string,
+ );
+ }
+ } else {
+ options.push(date);
+ }
+ }
+ } else {
+ options.push(...freetextOptions);
+ }
+
+ // save poll
+ try {
+ const encryptionKey = generatePassphrase();
+
+ // save poll
+ const poll = await Poll.create(
+ {
+ anonymousUser,
+ answerType,
+ description,
+ expirationDate,
+ forceAnswer,
+ options: options.map((option) => {
+ return { title: option };
+ }),
+ pollType,
+ title,
+ },
+ encryptionKey,
+ );
+
+ // redirect to new poll
+ await this.router.transitionTo('poll.participation', poll.id, {
+ queryParams: {
+ encryptionKey,
+ },
+ });
+ } catch (err) {
+ this.savingPollFailed = true;
+
+ reportError(err);
+ }
+ }
+
+ @action
+ resetSavingPollFailedState() {
+ this.savingPollFailed = false;
+ }
+}
+
+declare module '@glint/environment-ember-loose/registry' {
+ export default interface Registry {
+ CreateSettings: typeof CreateSettingsComponent;
+ }
+}
diff --git a/app/templates/create/settings.hbs b/app/templates/create/settings.hbs
index e458468..6971585 100644
--- a/app/templates/create/settings.hbs
+++ b/app/templates/create/settings.hbs
@@ -1,113 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file