Forms hinzugefügt

This commit is contained in:
R40fendt
2025-12-24 00:26:44 +01:00
parent 3576b88bf5
commit b5506cb44c
5 changed files with 493 additions and 331 deletions

View File

@@ -11,7 +11,6 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="manifest" href="./manifest.json">
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;700&display=swap" as="style" <link rel="preload" href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;700&display=swap" as="style"
onload="this.onload=null;this.rel='stylesheet'"> onload="this.onload=null;this.rel='stylesheet'">
<noscript> <noscript>

View File

@@ -1,52 +0,0 @@
{
"name": "Amedorf & Ritzenbergen",
"short_name": "ritzenbergen.de",
"theme_color": "#FFBF00",
"background_color": "#FE9A2E",
"display": "fullScreen",
"orientation": "portrait",
"scope": "/",
"start_url": "https://ritzenbergen.netlify.app/",
"icons": [
{
"src": "images/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "images/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "images/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "images/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "images/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "images/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "images/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "images/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

View File

@@ -0,0 +1,93 @@
<script lang="ts" setup>
import RitzenbergenLib from "../ritzenbergenlib.ts";
import { defineProps, ref } from "vue";
const props = defineProps({
form: {
type: RitzenbergenLib.Formular,
required: true,
},
});
const form = props.form;
let results = ref([]);
fetch(
RitzenbergenLib.RitzenbergenLib.api(
"/formulare/get_results.php?id=" + form.id
)
)
.then((res) => res.json())
.then((data) => {
results.value = data;
});
const myfields = [];
form.fields.forEach((field: RitzenbergenLib.Field) => {
if (myfields.find((el) => el.name == field.name) == undefined) {
myfields.push(field);
}
});
function prettyResult(result: any) {
if (result == undefined) {
return "";
}
if (result.value instanceof Array) {
let tempresult = result.value;
let cancel = false;
tempresult = tempresult.map((el) => {
let field = form.fields.find((f) => f.value == el);
if (field == undefined) {
cancel = true;
return el;
}
return field.displayvalue ?? el;
});
if (!cancel) result.value = tempresult;
return result.value.join(", ");
}
if (result.type == "radio") {
let field = form.fields.find((f) => f.value == result.value);
if (field != undefined) {
return field.displayvalue ?? result.value;
}
}
return result.value;
}
</script>
<template>
<h1>Ergebnisse {{ form.name }}</h1>
<table>
<thead>
<tr>
<td v-for="(field, i) in myfields" :key="i">
{{ field.displayname ?? field.name }}
</td>
<td>Zeitstempel</td>
</tr>
</thead>
<tbody>
<tr v-for="(result, ri) in results" :key="ri">
<td v-for="(field, fi) in myfields" :key="fi" :style="field.type=='color'?{ 'backgroundColor': result.data.find((el) => el.name == field.name).value, width: '10px', height: '10px' }:{}">
<span v-if="field.type!='color'">{{
prettyResult(
result.data.find(
(el) =>
el.name == field.name ||
el.name + "[]" == field.name
)
)
}}</span>
<span v-else ></span>
</td>
<td>{{ result.timestamp }}</td>
</tr>
</tbody>
</table>
</template>
<style scoped>
@import "../assets/css/bulitipp2.css";
</style>

View File

@@ -1,183 +1,135 @@
<script lang="ts"> <script lang="ts" setup>
import $ from "jquery"; import RitzenbergenLib from "../../ritzenbergenlib.ts";
import RitzenbergenLib from "../../ritzenbergenlib"; import FormResults from "../FormResults.vue";
import { ref } from "vue";
import Modal from "../Modal.vue"; import Modal from "../Modal.vue";
export default {
data() {
return {
openedModals: [],
formValues: [],
RitzenbergenLib: RitzenbergenLib.RitzenbergenLib,
};
},
computed: {
forms() {
let result: any[] = [];
$.ajax(RitzenbergenLib.RitzenbergenLib.api("/get_forms.php"), {
async: false,
crossDomain: true,
success: function (data: string) {
result = JSON.parse(data);
console.log(result);
},
});
result.forEach((element) => {
this.formValues.push({
value1: "",
value2: "",
});
});
return result;
}
},
mounted(){
if(this.$route.path=="/anmeldeformular"){
const hash = this.$route.path.replace("/","");
console.log(this.$refs[hash])
this.$refs[hash].scrollIntoView();
this.$router.push("/");
}
},
components: {
Modal,
},
methods: {
process_minitext(minitext: string) {
let count = 0;
return minitext.replace("{0}", count.toString());
//return minitext;
},
submit(event) {
let value1 = this.formValues[event.target.dataset.i].value1;
let value2 = this.formValues[event.target.dataset.i].value2;
let formid = event.target.dataset.formid;
$.ajax(RitzenbergenLib.api("submit_form.php"), { const Formular = RitzenbergenLib.Formular;
async: false, const Field = RitzenbergenLib.Field;
crossDomain: true, const forms = ref([] as Formular[]);
data: { formid, value1, value2 }, Formular.getForms().then((f) => {
}); forms.value = f;
});
function submit($event: Event) {
const url = new URL(
RitzenbergenLib.RitzenbergenLib.api("/formulare/submit.php")
);
const formData = new FormData($event.target);
fetch(url.toString(), {
method: "POST",
body: formData
}).then(() => {
forms.value = Formular.getForms().then((f) => {
forms.value = f;
});
});
}
const modalOpened=ref<boolean>(false);
const openedForm=ref<Formular|null>(null);
function openModal(form: Formular){
openedForm.value=form;
modalOpened.value=true;
}
console.log(formid, value1, value2);
},
formresults(formid){
let result: any[] = [];
$.ajax(RitzenbergenLib.RitzenbergenLib.api("/get_ergebnisse.php"), {
async: false,
crossDomain: true,
success: function (data: string) {
result = JSON.parse(data);
},
data: {formid}
});
return result;
}
},
};
</script> </script>
<template> <template>
<section ref="anmeldeformular" id="anmeldeformular"> <Modal v-show="modalOpened" @closemodal="modalOpened=false">
<section class="form5 cid-u6k7q0BfGa"> <FormResults v-if="openedForm" :form="openedForm"/>
<div class="container" v-for="(form, i) in forms"> </Modal>
<div class="row justify-content-center"> <section ref="anmeldeformular" id="anmeldeformular">
<div class="col-12 content-head"> <section class="form5 cid-u6k7q0BfGa">
<div class="mbr-section-head mb-5"> <div class="container" v-for="(form, i) in forms" :key="i">
<h3 <div class="row justify-content-center">
class="mbr-section-title mbr-fonts-style align-center mb-0 display-2" <div class="col-12 content-head">
> <div class="mbr-section-head mb-5">
<strong>{{ form.ueberschrift }}</strong> <h3
</h3> class="mbr-section-title mbr-fonts-style align-center mb-0 display-2"
<br /> >
<h5 style="text-align: center"> <strong>{{ form.name }}</strong>
<b></b> <br /> </h3>
{{ form.inhalt }} <br />
</h5> <h5 style="text-align: center">
<br /> <b @click="openModal(form)">{{ form.minitext }}
</b> <br />
</h5>
<br />
</div>
</div>
</div>
<div class="row justify-content-center">
<div
class="col-lg-8 mx-auto mbr-form"
data-form-type="formoid"
>
<form
class="mbr-form form-with-styler"
data-form-title="Form Name"
:data-formid="form.id"
:data-i="i"
@submit.prevent="submit"
>
<div v-for="(field, j) in form.fields" :key="j">
<label
v-if="field.placeholder == null"
:for="'field-' + field.id"
>
{{
field.displayvalue ?? field.displayname ?? field.name
}}:
</label>
<input
v-if="field.type != 'textarea'"
:id="'field-' + field.id"
:type="field.type"
:name="field.name"
:placeholder="field.placeholder"
:required="field.required"
:maxlength="field.maxlength"
:min="field.min"
:max="field.max"
:checked="field.checked"
:title="field.title"
:value="field.value"
/>
<textarea
v-else
:id="'field-' + field.id"
:name="field.name"
:placeholder="field.placeholder"
:required="field.required"
:maxlength="field.maxlength"
:title="field.title"
:value="field.value"
></textarea>
<span v-if="field.type == 'range'"
><br />{{ field.value }}</span
>
</div>
<Modal <div
v-if="form.public" class="col-lg-12 col-md-12 col-sm-12 align-center mbr-section-btn"
@closemodal=" >
openedModals.splice(openedModals.indexOf(form.id), 1) <button
" type="submit"
v-show="openedModals.includes(form.id)" class="btn btn-primary display-7 formular-submit-button"
> >
<h1>{{ form.modalueberschrift }}</h1> Absenden
<table> </button>
<tbody> </div>
<tr> <input type="hidden" :value="form.id" name="internalformid" />
<td>{{ form.labelone }}</td> </form>
<td>{{ form.labeltwo }}</td> </div>
<td>Datum</td> </div>
</tr> </div>
<tr v-for="result in formresults(form.id)"> </section>
<td>{{ result.value1 }}</td> </section>
<td>{{ result.value2 }}</td>
<td>{{ result.timestamp }}</td>
</tr>
</tbody>
</table>
</Modal>
<p style="text-align: center" @click="openedModals.push(form.id)">
{{ process_minitext(form.minitext) }}<br /><br />
</p>
</div>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-8 mx-auto mbr-form" data-form-type="formoid">
<form
class="mbr-form form-with-styler"
data-form-title="Form Name"
@submit.prevent="submit"
:data-formid="form.id"
:data-i="i"
>
<div class="dragArea row">
<div class="col-md col-sm-12 form-group mb-3" data-for="name">
<input
type="text"
maxlength="128"
name="name"
:placeholder="form.labelone"
data-form-field="name"
class="form-control"
value=""
id="name-form02-0"
v-model="formValues[i].value1"
required
/>
</div>
<div class="col-12 form-group mb-3" data-for="textarea">
<input
type="text"
name="textarea"
maxlength="128"
:placeholder="form.labeltwo"
data-form-field="textarea"
class="form-control"
id="textarea-form02-0"
v-model="formValues[i].value2"
required
/>
</div>
<div
class="col-lg-12 col-md-12 col-sm-12 align-center mbr-section-btn"
>
<button
type="submit"
class="btn btn-primary display-7 formular-submit-button"
>
Absenden
</button>
</div>
</div>
<input type="hidden" :value="form.id" name="id" />
</form>
</div>
</div>
</div>
</section>
</section>
</template> </template>
<style></style> <style scoped>
label {
margin-right: 10px;
}
</style>

View File

@@ -1,127 +1,297 @@
import $ from "jquery"; import $ from "jquery";
import { ref } from "vue";
class User { class User {
public username: string; public username: string;
public kuerzel: string; public kuerzel: string;
public points: number; public points: number;
public id: number; public id: number;
constructor (username: string, kuerzel: string, points: number, id: number) { constructor(username: string, kuerzel: string, points: number, id: number) {
this.username = username; this.username = username;
this.kuerzel = kuerzel; this.kuerzel = kuerzel;
this.points=points; this.points = points;
this.id=id; this.id = id;
} }
hatgetippt():boolean{ hatgetippt(): boolean {
var hatgetippt=false; var hatgetippt = false;
$.ajax(RitzenbergenLib.api("/bulitipp/hatgetippt.php?userid="+this.id),{ $.ajax(
async: false, RitzenbergenLib.api("/bulitipp/hatgetippt.php?userid=" + this.id),
success(response): any{ {
hatgetippt=response==1; async: false,
console.log(response); success(response): any {
} hatgetippt = response == 1;
}); console.log(response);
return hatgetippt; },
} }
);
return hatgetippt;
}
} }
class SpieltagSumme { class SpieltagSumme {
public user: User; public user: User;
public tsPoints: number; public tsPoints: number;
constructor (user: User, tsPoints: number) { constructor(user: User, tsPoints: number) {
this.user = user; this.user = user;
this.tsPoints = tsPoints; this.tsPoints = tsPoints;
} }
} }
class RitzenbergenLib { class RitzenbergenLib {
static get_img(mypath: string) { static get_img(mypath: string) {
if(mypath.startsWith("/")) return "https://bilder.ritzenbergen.de"+mypath; if (mypath.startsWith("/"))
else return "https://bilder.ritzenbergen.de/"+mypath; return "https://bilder.ritzenbergen.de" + mypath;
} else return "https://bilder.ritzenbergen.de/" + mypath;
static api(path:string){ }
if(path.startsWith("/")) return "http://192.168.188.38/Jonas/ritzenbergenapi"+path; static api(path: string) {
else return "http://192.168.188.38/Jonas/ritzenbergenapi/"+path; if (path.startsWith("/"))
} return "http://192.168.188.38/Jonas/ritzenbergenapi" + path;
else return "http://192.168.188.38/Jonas/ritzenbergenapi/" + path;
}
} }
class Paarung { class Paarung {
public heim: string; public heim: string;
public gast: string; public gast: string;
public id: number; public id: number;
constructor (heim: string, gast: string, id: number) { constructor(heim: string, gast: string, id: number) {
this.heim = heim; this.heim = heim;
this.gast = gast; this.gast = gast;
this.id=id; this.id = id;
} }
} }
class Ergebnis { class Ergebnis {
paarung: Paarung; paarung: Paarung;
heim: number; heim: number;
gast: number; gast: number;
constructor (paarung: Paarung, heim: number, gast: number) { constructor(paarung: Paarung, heim: number, gast: number) {
this.paarung = paarung; this.paarung = paarung;
this.heim = heim; this.heim = heim;
this.gast = gast; this.gast = gast;
} }
} }
class Tipp{ class Tipp {
heim: number|null; heim: number | null;
gast: number|null; gast: number | null;
paarung: Paarung|null; paarung: Paarung | null;
constructor (paarung: Paarung|null, heim: number|null, gast: number|null) { constructor(
this.heim = heim; paarung: Paarung | null,
this.gast = gast; heim: number | null,
this.paarung = paarung; gast: number | null
} ) {
this.heim = heim;
this.gast = gast;
this.paarung = paarung;
}
} }
class Spiel { class Spiel {
public paarung: Paarung; public paarung: Paarung;
public result: [number, number]|null; public result: [number, number] | null;
public tipp: [number, number]|null; public tipp: [number, number] | null;
constructor (paarung: Paarung, result: [number, number], tipp: [number, number]|null) { constructor(
this.paarung = paarung; paarung: Paarung,
this.result = result; result: [number, number],
this.tipp = tipp; tipp: [number, number] | null
} ) {
public calcPoints(){ this.paarung = paarung;
if(this.tipp==null) return 0; this.result = result;
if(this.result[0]==this.tipp[0] && this.result[1]==this.tipp[1]) return 3; this.tipp = tipp;
let differenztipp=this.tipp[0]-this.tipp[1]; }
let differenz=this.result[0]-this.result[1]; public calcPoints() {
if(differenztipp==differenz) return 2; if (this.tipp == null) return 0;
if( if (this.result[0] == this.tipp[0] && this.result[1] == this.tipp[1])
(this.tipp[0]>this.tipp[1] && this.result[0]>this.result[1]) || return 3;
(this.tipp[0]<this.tipp[1] && this.result[0]<this.result[1]) let differenztipp = this.tipp[0] - this.tipp[1];
) return 1; let differenz = this.result[0] - this.result[1];
return 0; if (differenztipp == differenz) return 2;
} if (
public static async fetchSpiele(spieltag: number, userid: number):Spiel[]{ (this.tipp[0] > this.tipp[1] && this.result[0] > this.result[1]) ||
let params=new URLSearchParams({ (this.tipp[0] < this.tipp[1] && this.result[0] < this.result[1])
spieltag: spieltag+1, )
user: userid return 1;
}); return 0;
return fetch(RitzenbergenLib.api("/bulitipp/spieltag-user.php?")+params.toString()).then((response)=>{ }
return response.json(); public static async fetchSpiele(spieltag: number, userid: number): Spiel[] {
}).then((data)=>{ let params = new URLSearchParams({
return data.data; spieltag: spieltag + 1,
}).then((data)=>{ user: userid,
return data.map((el)=>{ });
return new Spiel(new Paarung(el.paarung.heim, el.paarung.gast, el.paarung.id),el.result, el.tipp); return fetch(
}); RitzenbergenLib.api("/bulitipp/spieltag-user.php?") +
params.toString()
)
.then((response) => {
return response.json();
})
.then((data) => {
return data.data;
})
.then((data) => {
return data.map((el) => {
return new Spiel(
new Paarung(
el.paarung.heim,
el.paarung.gast,
el.paarung.id
),
el.result,
el.tipp
);
}); });
});
}
}
class Formular {
public id: number;
public name: string;
public minitext: string;
public ispublic: boolean;
public multiple: boolean;
public fields=ref<Field[]>([]);
constructor(
id: number,
name: string,
minitext: string,
ispublic: boolean,
multiple: boolean
) {
this.id = id;
this.name = name;
this.minitext = minitext;
this.ispublic = ispublic;
this.multiple = multiple;
this.getFields().then((fields)=>this.fields.value=fields);
}
public static async getForms(): Promise<Formular[]> {
let forms: Formular[] = [];
forms = await fetch(
RitzenbergenLib.api("/formulare/get_formulare.php"),
{
method: "GET",
}
)
.then((response) => response.json())
.then((result) =>
result.map(
(el: any) =>
new Formular(
el.id,
el.name,
el.minitext,
el.public,
el.multiple
)
)
);
return forms;
}
private async getFields(): Promise<Field[]> {
return fetch(
RitzenbergenLib.api(
"/formulare/get_fields.php?formular=" + this.id
),
{
method: "GET",
}
)
.then((response) => response.json())
.then((result) =>
result.map(
(el: any) =>
new Field(el.formular, el.name, el.value, el.type, {
id: el.id,
displayname: el.displayname,
displayvalue: el.displayvalue,
placeholder: el.placeholder,
title: el.title,
required: el.required == 1,
maxlength: el.maxlength,
min: el.min,
max: el.max,
multiple: el.multiple == 1,
checked: el.checked == 1,
})
)
);
}
}
type FieldType =
| "text"
| "password"
| "number"
| "range"
| "date"
| "time"
| "checkbox"
| "radio"
| "color"
| "submit"
| "textarea";
class Field {
id?: number;
formular: number;
name: string;
displayname?: string | null;
value: string;
displayvalue?: string | null;
placeholder?: string | null;
type: FieldType;
title?: string | null;
required: boolean;
maxlength?: number | null;
min?: number | null;
max?: number | null;
checked?: boolean | null;
constructor(
formular: number,
name: string,
value: string,
type: FieldType,
options?: {
id?: number;
displayname?: string | null;
displayvalue?: string | null;
placeholder?: string | null;
title?: string | null;
required?: boolean;
maxlength?: number | null;
min?: number | null;
max?: number | null;
multiple?: boolean | null;
checked?: boolean | null;
} }
) {
this.id = options?.id;
this.formular = formular;
this.name = name;
this.displayname = options?.displayname ?? null;
this.value = value;
this.displayvalue = options?.displayvalue ?? null;
this.placeholder = options?.placeholder ?? null;
this.type = type;
this.title = options?.title ?? null;
this.required = options?.required ?? false;
this.maxlength = options?.maxlength ?? null;
this.min = options?.min ?? null;
this.max = options?.max ?? null;
this.checked = options?.checked ?? null;
}
} }
export default { export default {
RitzenbergenLib, RitzenbergenLib,
User, User,
SpieltagSumme, SpieltagSumme,
Paarung, Paarung,
Ergebnis, Ergebnis,
Tipp, Tipp,
Spiel Spiel,
} Formular,
Field,
};