some minor fixes

This commit is contained in:
2025-02-10 20:56:55 +01:00
parent c3f306575f
commit 12308af1c4
9 changed files with 138 additions and 31 deletions

View File

@ -3,14 +3,15 @@
## Development
```bash
docker compose -f docker-compose.yaml.prod up -d --build
docker compose up -d --build
docker compose exec -it backend python mange.py migrate
docker compose exec -it backend python mange.py createsuperuser
```
Po czym
- backend jest dostępny na porcie ```8000```
- frontend jest dostępny na porcie ```3000```
- backend jest dostępny na porcie ``8000``
- frontend jest dostępny na porcie ``3000``
## Produkcja
@ -21,4 +22,4 @@ docker compose -f docker-compose.yaml.prod exec -it backend python mange.py crea
docker compose -f docker-compose.yaml.prod exec -it backend python manage.py collectstatic
```
Po czym aplikacja jest dostępna na porcie ```8080```
Po czym aplikacja jest dostępna na porcie ``8080``

View File

@ -29,6 +29,7 @@ class Meal(models.Model):
class Meta:
verbose_name = _('Danie')
verbose_name_plural = _('Dania')
ordering = ['name',]
class Order(models.Model):

View File

@ -55,6 +55,8 @@ class MealSerializer(serializers.ModelSerializer):
class MealViewSet(viewsets.ModelViewSet):
queryset = Meal.objects.all()
serializer_class = MealSerializer
filter_backends = [filters.OrderingFilter]
ordering = ['name']
class OrderSerializer(serializers.ModelSerializer):
@ -88,9 +90,9 @@ class OrderViewSet(viewsets.ModelViewSet):
ordering = ['-created_on']
def get_queryset(self):
five_minutes_ago = timezone.now() + datetime.timedelta(minutes=-5)
five_minutes_ago = timezone.now() + datetime.timedelta(minutes=-15)
return Order.objects.filter(
~Q(status=Order.StatusChoices.FINALIZED)
~Q(status__gte=Order.StatusChoices.READY)
| Q(updated_on__gte=five_minutes_ago)
)

View File

@ -5,8 +5,6 @@ services:
restart: unless-stopped
volumes:
- django_static_prod:/usr/src/app/static
ports:
- "8000:8000"
environment:
SECRET_KEY: ${SECRET_KEY}
DEBUG: False
@ -24,8 +22,6 @@ services:
restart: unless-stopped
volumes:
- ./frontend:/app
ports:
- "3000:3000"
redis:
restart: unless-stopped

View File

@ -16,6 +16,10 @@ textarea {
@apply p-1 ps-2 transition ease-in-out focus:outline-none border-b-2 border-b-gray-400 mb-2 focus:bg-gray-100 focus:border-gray-600 appearance-none;
}
.error {
@apply !bg-red-200 ring-2 ring-red-400;
}
form#form select {
@apply p-2 ps-2 rounded-md bg-gray-100;
}

View File

@ -84,10 +84,10 @@ export default function Home() {
}
className="form border-2 my-2 border-gray-500"
>
<option value="1">Zamówienie złożone</option>
{/* <option value="1">Zamówienie złożone</option> */}
<option value="2">Zamówienie w trakcie przygotowywania</option>
<option value="3">Zamówienie gotowe</option>
<option value="4">Zamówienie zrealizowane</option>
{/* <option value="4">Zamówienie zrealizowane</option> */}
</select>
</h3>
<div className="">
@ -103,7 +103,7 @@ export default function Home() {
onChange={(e) => update_finished(oi, i, e.target.checked)}
/>
<div>
<p className="text-lg">{dish.item} - {dish.takeout ? 'Na wynos' : 'Na miejscu'}</p>
<p className="text-lg">{dish.item}{dish.times > 1 ? ` - x${dish.times}`: ''} - {dish.takeout ? 'Na wynos' : 'Na miejscu'}</p>
<div>{dish.additional_info}</div>
</div>
</li>

View File

@ -3,6 +3,7 @@ export type Dish = {
additional_info: string;
finished: boolean;
takeout: boolean;
times: number;
};
export type Order = {
@ -29,6 +30,8 @@ export function getOrderBg(order: Order): string {
}
export function getDishBg(dish: Dish): string {
if (dish.finished) return 'bg-red-200 border-red-400';
return dish.takeout
? 'bg-blue-300 border-blue-500'
: 'bg-green-300 border-green-500';

View File

@ -8,10 +8,15 @@ import { fetcher } from '@/app/api/tools';
import useSWR from 'swr';
import { Dish } from '@/app/tools';
type FormDish = Dish & {
filter: string;
};
type FormValues = {
status: number;
client: string;
realization_time: string;
data: Dish[];
data: FormDish[];
};
export default function App() {
@ -24,22 +29,37 @@ export default function App() {
control,
handleSubmit,
formState: { errors },
getValues,
setValue,
watch,
} = useForm<FormValues>({
defaultValues: {
status: 2,
client: '',
realization_time: new Date().toLocaleTimeString('pl-PL', { hour: '2-digit', minute: '2-digit' }),
realization_time: new Date().toLocaleTimeString('pl-PL', {
hour: '2-digit',
minute: '2-digit',
}),
data: [
{ item: 'Inne', additional_info: '', finished: false, takeout: false },
{
item: '',
additional_info: '',
finished: false,
takeout: false,
times: 1,
filter: '',
},
],
},
mode: 'all',
criteriaMode: 'all',
shouldFocusError: true
});
const { fields, append, remove } = useFieldArray({
name: 'data',
control,
});
const onSubmit = (data: FormValues) => {
console.log(data);
fetch('/api/orders', {
method: 'POST',
body: JSON.stringify({ waiter: id, ...data }),
@ -54,6 +74,8 @@ export default function App() {
if (error) return <div>Błąd przy ładowaniu danych</div>;
if (isLoading) return <div>Ładowanie</div>;
watch('data')
return (
<>
<form
@ -95,21 +117,56 @@ export default function App() {
required: false,
})}
/>
<div className="basis-1/3">
<div className="basis-1/3 gap-2">
<label htmlFor={`data.${index}.item`}>Danie</label>
<input
{...register(`data.${index}.filter` as const, {
required: false,
})}
placeholder='Wyszukaj danie'
className={errors?.data?.[index]?.filter ? 'error' : ''}
onChange={(e) => setValue(`data.${index}.item`, data
?.filter((data: { id: number; name: string }) =>
data.name
.toLowerCase()
.includes(
e.target.value.toLowerCase()
)
)[0].name, {shouldValidate: true})}
/>
<select
{...register(`data.${index}.item` as const, {
required: true,
})}
className={errors?.data?.[index]?.item ? 'error' : ''}
>
<option value="Inne">Inne</option>
{data?.map((data: { id: number; name: string }) => (
<option key={data.name} value={data.name}>
{data.name}
</option>
))}
{!!getValues(`data.${index}.filter`) ? (
null
) : (
<option value="Inne">Inne</option>
)}
{data
?.filter((data: { id: number; name: string }) =>
data.name
.toLowerCase()
.includes(
getValues(`data.${index}.filter`).toLowerCase()
)
)
.map((data: { id: number; name: string }) => (
<option key={data.name} value={data.name}>
{data.name}
</option>
))}
</select>
<label htmlFor={`data.${index}.times`}>Ilość</label>
<input
{...register(`data.${index}.times` as const, {
required: false,
})}
type="number"
className={errors?.data?.[index]?.times ? 'error' : ''}
/>
<section className="flex flex-row my-2 gap-2">
<label htmlFor={`data.${index}.takeout`}>Na wynos</label>
<input
@ -157,6 +214,8 @@ export default function App() {
additional_info: '',
finished: false,
takeout: false,
times: 1,
filter: '',
})
}
>

View File

@ -9,7 +9,7 @@ import { OrderID } from '@/app/components';
export default function Home() {
const { id } = useParams();
const { data, error, isLoading } = useSWR(
const { data, error, isLoading, mutate } = useSWR(
`/api/orders?waiter=${id}`,
fetcher,
{
@ -17,6 +17,30 @@ export default function Home() {
}
);
const update_finished = (o: number, i: number, v: boolean) => {
const d = data;
d[o].data[i].finished = v;
fetch(`/api/orders?id=${d[o].id}`, {
method: 'PUT',
body: JSON.stringify(d[o]),
headers: {
'Content-Type': 'application/json',
},
}).then(() => mutate(d));
};
const update_status = (o: number, v: number) => {
const d = data;
d[o].status = v;
fetch(`/api/orders?id=${d[o].id}`, {
method: 'PUT',
body: JSON.stringify(d[o]),
headers: {
'Content-Type': 'application/json',
},
}).then(() => mutate(d));
};
if (error) return <div>Błąd przy ładowaniu danych</div>;
if (isLoading) return <div>Ładowanie</div>;
@ -29,25 +53,42 @@ export default function Home() {
</p>
<p className="text-4xl">Zamówienia:</p>
<ul className="max-w-screen-md w-full">
{data?.map((order: Order) => (
{data?.map((order: Order, oi: number) => (
<li
key={order.id}
className={`m-2 p-2 rounded-md border-2 ${getOrderBg(order)}`}
>
<OrderID order={order} />
<h2 className="text-xl">Kelner: {order.waiter_name}</h2>
<h2 className="text-xl">{order.waiter_name}</h2>
{ (order.client) ? <h2 className="text-xl">Klient: {order.client}</h2> : <></>}
<h3>{order.status_name}</h3>
<h3>
<select
value={order.status}
onChange={(e) =>
update_status(oi, e.target.value as unknown as number)
}
className="form border-2 my-2 border-gray-500"
>
{/* <option value="1">Zamówienie złożone</option> */}
<option value="2">Zamówienie w trakcie przygotowywania</option>
<option value="3">Zamówienie gotowe</option>
{/* <option value="4">Zamówienie zrealizowane</option> */}
</select>
</h3>
<div className="">
<ul>
{order.data.map((dish) => (
{order.data.map((dish, i) => (
<li
key={dish.item}
className={`p-2 m-2 flex gap-4 border-2 ${getDishBg(dish)}`}
>
<input type="checkbox" checked={dish.finished} readOnly />
<input
type="checkbox"
checked={dish.finished}
onChange={(e) => update_finished(oi, i, e.target.checked)}
/>
<div>
<p className="text-lg">{dish.item} - {dish.takeout ? 'Na wynos' : 'Na miejscu'}</p>
<p className="text-lg">{dish.item}{dish.times > 1 ? ` - x${dish.times}`: ''} - {dish.takeout ? 'Na wynos' : 'Na miejscu'}</p>
<div>{dish.additional_info}</div>
</div>
</li>