some minor fixes
This commit is contained in:
@ -3,14 +3,15 @@
|
|||||||
## Development
|
## Development
|
||||||
|
|
||||||
```bash
|
```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 migrate
|
||||||
docker compose exec -it backend python mange.py createsuperuser
|
docker compose exec -it backend python mange.py createsuperuser
|
||||||
```
|
```
|
||||||
|
|
||||||
Po czym
|
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
|
## 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
|
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``
|
||||||
|
@ -29,6 +29,7 @@ class Meal(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('Danie')
|
verbose_name = _('Danie')
|
||||||
verbose_name_plural = _('Dania')
|
verbose_name_plural = _('Dania')
|
||||||
|
ordering = ['name',]
|
||||||
|
|
||||||
|
|
||||||
class Order(models.Model):
|
class Order(models.Model):
|
||||||
|
@ -55,6 +55,8 @@ class MealSerializer(serializers.ModelSerializer):
|
|||||||
class MealViewSet(viewsets.ModelViewSet):
|
class MealViewSet(viewsets.ModelViewSet):
|
||||||
queryset = Meal.objects.all()
|
queryset = Meal.objects.all()
|
||||||
serializer_class = MealSerializer
|
serializer_class = MealSerializer
|
||||||
|
filter_backends = [filters.OrderingFilter]
|
||||||
|
ordering = ['name']
|
||||||
|
|
||||||
|
|
||||||
class OrderSerializer(serializers.ModelSerializer):
|
class OrderSerializer(serializers.ModelSerializer):
|
||||||
@ -88,9 +90,9 @@ class OrderViewSet(viewsets.ModelViewSet):
|
|||||||
ordering = ['-created_on']
|
ordering = ['-created_on']
|
||||||
|
|
||||||
def get_queryset(self):
|
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(
|
return Order.objects.filter(
|
||||||
~Q(status=Order.StatusChoices.FINALIZED)
|
~Q(status__gte=Order.StatusChoices.READY)
|
||||||
| Q(updated_on__gte=five_minutes_ago)
|
| Q(updated_on__gte=five_minutes_ago)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,8 +5,6 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- django_static_prod:/usr/src/app/static
|
- django_static_prod:/usr/src/app/static
|
||||||
ports:
|
|
||||||
- "8000:8000"
|
|
||||||
environment:
|
environment:
|
||||||
SECRET_KEY: ${SECRET_KEY}
|
SECRET_KEY: ${SECRET_KEY}
|
||||||
DEBUG: False
|
DEBUG: False
|
||||||
@ -24,8 +22,6 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ./frontend:/app
|
- ./frontend:/app
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
@ -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;
|
@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 {
|
form#form select {
|
||||||
@apply p-2 ps-2 rounded-md bg-gray-100;
|
@apply p-2 ps-2 rounded-md bg-gray-100;
|
||||||
}
|
}
|
||||||
|
@ -84,10 +84,10 @@ export default function Home() {
|
|||||||
}
|
}
|
||||||
className="form border-2 my-2 border-gray-500"
|
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="2">Zamówienie w trakcie przygotowywania</option>
|
||||||
<option value="3">Zamówienie gotowe</option>
|
<option value="3">Zamówienie gotowe</option>
|
||||||
<option value="4">Zamówienie zrealizowane</option>
|
{/* <option value="4">Zamówienie zrealizowane</option> */}
|
||||||
</select>
|
</select>
|
||||||
</h3>
|
</h3>
|
||||||
<div className="">
|
<div className="">
|
||||||
@ -103,7 +103,7 @@ export default function Home() {
|
|||||||
onChange={(e) => update_finished(oi, i, e.target.checked)}
|
onChange={(e) => update_finished(oi, i, e.target.checked)}
|
||||||
/>
|
/>
|
||||||
<div>
|
<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>{dish.additional_info}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -3,6 +3,7 @@ export type Dish = {
|
|||||||
additional_info: string;
|
additional_info: string;
|
||||||
finished: boolean;
|
finished: boolean;
|
||||||
takeout: boolean;
|
takeout: boolean;
|
||||||
|
times: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Order = {
|
export type Order = {
|
||||||
@ -29,6 +30,8 @@ export function getOrderBg(order: Order): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getDishBg(dish: Dish): string {
|
export function getDishBg(dish: Dish): string {
|
||||||
|
if (dish.finished) return 'bg-red-200 border-red-400';
|
||||||
|
|
||||||
return dish.takeout
|
return dish.takeout
|
||||||
? 'bg-blue-300 border-blue-500'
|
? 'bg-blue-300 border-blue-500'
|
||||||
: 'bg-green-300 border-green-500';
|
: 'bg-green-300 border-green-500';
|
||||||
|
@ -8,10 +8,15 @@ import { fetcher } from '@/app/api/tools';
|
|||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { Dish } from '@/app/tools';
|
import { Dish } from '@/app/tools';
|
||||||
|
|
||||||
|
type FormDish = Dish & {
|
||||||
|
filter: string;
|
||||||
|
};
|
||||||
|
|
||||||
type FormValues = {
|
type FormValues = {
|
||||||
|
status: number;
|
||||||
client: string;
|
client: string;
|
||||||
realization_time: string;
|
realization_time: string;
|
||||||
data: Dish[];
|
data: FormDish[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
@ -24,22 +29,37 @@ export default function App() {
|
|||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
|
getValues,
|
||||||
|
setValue,
|
||||||
|
watch,
|
||||||
} = useForm<FormValues>({
|
} = useForm<FormValues>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
status: 2,
|
||||||
client: '',
|
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: [
|
data: [
|
||||||
{ item: 'Inne', additional_info: '', finished: false, takeout: false },
|
{
|
||||||
|
item: '',
|
||||||
|
additional_info: '',
|
||||||
|
finished: false,
|
||||||
|
takeout: false,
|
||||||
|
times: 1,
|
||||||
|
filter: '',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
mode: 'all',
|
mode: 'all',
|
||||||
|
criteriaMode: 'all',
|
||||||
|
shouldFocusError: true
|
||||||
});
|
});
|
||||||
const { fields, append, remove } = useFieldArray({
|
const { fields, append, remove } = useFieldArray({
|
||||||
name: 'data',
|
name: 'data',
|
||||||
control,
|
control,
|
||||||
});
|
});
|
||||||
const onSubmit = (data: FormValues) => {
|
const onSubmit = (data: FormValues) => {
|
||||||
console.log(data);
|
|
||||||
fetch('/api/orders', {
|
fetch('/api/orders', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({ waiter: id, ...data }),
|
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 (error) return <div>Błąd przy ładowaniu danych</div>;
|
||||||
if (isLoading) return <div>Ładowanie</div>;
|
if (isLoading) return <div>Ładowanie</div>;
|
||||||
|
|
||||||
|
watch('data')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<form
|
<form
|
||||||
@ -95,21 +117,56 @@ export default function App() {
|
|||||||
required: false,
|
required: false,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
<div className="basis-1/3">
|
<div className="basis-1/3 gap-2">
|
||||||
<label htmlFor={`data.${index}.item`}>Danie</label>
|
<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
|
<select
|
||||||
{...register(`data.${index}.item` as const, {
|
{...register(`data.${index}.item` as const, {
|
||||||
required: true,
|
required: true,
|
||||||
})}
|
})}
|
||||||
className={errors?.data?.[index]?.item ? 'error' : ''}
|
className={errors?.data?.[index]?.item ? 'error' : ''}
|
||||||
>
|
>
|
||||||
|
{!!getValues(`data.${index}.filter`) ? (
|
||||||
|
null
|
||||||
|
) : (
|
||||||
<option value="Inne">Inne</option>
|
<option value="Inne">Inne</option>
|
||||||
{data?.map((data: { id: number; name: string }) => (
|
)}
|
||||||
|
{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}>
|
<option key={data.name} value={data.name}>
|
||||||
{data.name}
|
{data.name}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</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">
|
<section className="flex flex-row my-2 gap-2">
|
||||||
<label htmlFor={`data.${index}.takeout`}>Na wynos</label>
|
<label htmlFor={`data.${index}.takeout`}>Na wynos</label>
|
||||||
<input
|
<input
|
||||||
@ -157,6 +214,8 @@ export default function App() {
|
|||||||
additional_info: '',
|
additional_info: '',
|
||||||
finished: false,
|
finished: false,
|
||||||
takeout: false,
|
takeout: false,
|
||||||
|
times: 1,
|
||||||
|
filter: '',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -9,7 +9,7 @@ import { OrderID } from '@/app/components';
|
|||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const { data, error, isLoading } = useSWR(
|
const { data, error, isLoading, mutate } = useSWR(
|
||||||
`/api/orders?waiter=${id}`,
|
`/api/orders?waiter=${id}`,
|
||||||
fetcher,
|
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 (error) return <div>Błąd przy ładowaniu danych</div>;
|
||||||
if (isLoading) return <div>Ładowanie</div>;
|
if (isLoading) return <div>Ładowanie</div>;
|
||||||
|
|
||||||
@ -29,25 +53,42 @@ export default function Home() {
|
|||||||
</p>
|
</p>
|
||||||
<p className="text-4xl">Zamówienia:</p>
|
<p className="text-4xl">Zamówienia:</p>
|
||||||
<ul className="max-w-screen-md w-full">
|
<ul className="max-w-screen-md w-full">
|
||||||
{data?.map((order: Order) => (
|
{data?.map((order: Order, oi: number) => (
|
||||||
<li
|
<li
|
||||||
key={order.id}
|
key={order.id}
|
||||||
className={`m-2 p-2 rounded-md border-2 ${getOrderBg(order)}`}
|
className={`m-2 p-2 rounded-md border-2 ${getOrderBg(order)}`}
|
||||||
>
|
>
|
||||||
<OrderID order={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> : <></>}
|
{ (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="">
|
<div className="">
|
||||||
<ul>
|
<ul>
|
||||||
{order.data.map((dish) => (
|
{order.data.map((dish, i) => (
|
||||||
<li
|
<li
|
||||||
key={dish.item}
|
key={dish.item}
|
||||||
className={`p-2 m-2 flex gap-4 border-2 ${getDishBg(dish)}`}
|
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>
|
<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>{dish.additional_info}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
Reference in New Issue
Block a user